package com.xbongbong.saas.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.distributor.dto.DistributorContractOutStockDeleteBatchDTO;
import com.xbongbong.distributor.dto.DistributorContractOutStockEditAttrUpdateDTO;
import com.xbongbong.distributor.vo.DistributorContractOutStockDeleteBatchVO;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.paas.constant.MessageConstant;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.constant.TimeConstant;
import com.xbongbong.paas.domain.entity.PaasFormDataEntity;
import com.xbongbong.paas.domain.entity.PaasFormExplainEntity;
import com.xbongbong.paas.domain.entity.PaasProcessRelatedDataEntity;
import com.xbongbong.paas.domain.entity.ext.PaasFormDataEntityExt;
import com.xbongbong.paas.elasticsearch.model.PaasEsModel;
import com.xbongbong.paas.elasticsearch.util.EsHelper;
import com.xbongbong.paas.enums.DefaultTypeEnum;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.enums.FlowStatusEnum;
import com.xbongbong.paas.enums.IndexTypeEnum;
import com.xbongbong.paas.field.DefaultAttrPoJo;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.field.ItemPoJo;
import com.xbongbong.paas.help.CommonHelp;
import com.xbongbong.paas.help.FormDataValidateProductHelp;
import com.xbongbong.paas.help.ProFormHelp;
import com.xbongbong.paas.help.ProSaveHelp;
import com.xbongbong.paas.help.UserHelp;
import com.xbongbong.paas.help.subform.TransferSubFormHelper;
import com.xbongbong.paas.log.MongoLogHelp;
import com.xbongbong.paas.log.constant.LogMemoConstant;
import com.xbongbong.paas.log.pojo.InfoArrPojo;
import com.xbongbong.paas.model.PaasFormExplainModel;
import com.xbongbong.paas.model.PaasProcessRelatedDataModel;
import com.xbongbong.paas.pojo.dto.ParseSingleRowDataDTO;
import com.xbongbong.paas.pojo.dto.SaasFormSaveDTO;
import com.xbongbong.paas.pojo.dto.UserAndDepartmentGetDTO;
import com.xbongbong.paas.pojo.dto.ValidateDataDTO;
import com.xbongbong.paas.pojo.vo.PaasFormDataEsListVO;
import com.xbongbong.paas.pojo.vo.ParseSingleRowDataVO;
import com.xbongbong.paas.pojo.vo.UserAndDepartmentGetVO;
import com.xbongbong.paas.redis.PaasRedisHelper;
import com.xbongbong.paas.redis.RedisPrefixConstant;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.Arith;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.paas.toolbox.wrap.UserVO;
import com.xbongbong.paas.util.ExplainUtil;
import com.xbongbong.parent.parse.data.FormDataUpdateGetAnalysisDataHelp;
import com.xbongbong.pro.businessdata.pojo.dto.FormatExplainDTO;
import com.xbongbong.pro.constant.AttrLenthConstant;
import com.xbongbong.pro.constant.BusinessConstant;
import com.xbongbong.pro.constant.ElasticConstant;
import com.xbongbong.pro.contract.pojo.dto.ContractRestoreOutboundDTO;
import com.xbongbong.pro.detailtab.pojo.OneKeyProduceProductPojo;
import com.xbongbong.pro.domain.entity.LinkProductRelyEntity;
import com.xbongbong.pro.domain.entity.UpdateDataEntity;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.pro.enums.errorcodes.AssembleErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.OutstockErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.SettleAccountErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.TemplateErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.TransferErrorCodeEnum;
import com.xbongbong.pro.enums.fund.enums.ModelTypeEnum;
import com.xbongbong.pro.formexplain.pojo.dto.HandlerExplainInLinkItemDTO;
import com.xbongbong.pro.instock.pojo.dto.RetMaterielListDTO;
import com.xbongbong.pro.instockproduct.pojo.vo.InstockProductDeleteBatchVO;
import com.xbongbong.pro.inventory.pojo.dto.InventoryResetOutstockIdDTO;
import com.xbongbong.pro.message.constant.OutstockPushConstant;
import com.xbongbong.pro.message.enums.PushTypeEnum;
import com.xbongbong.pro.message.pojo.PushRefTypePojo;
import com.xbongbong.pro.message.pojo.dto.MessageRabbitMqDTO;
import com.xbongbong.pro.outstock.pojo.dto.OutstockUpdateBatchDTO;
import com.xbongbong.pro.outstock.pojo.dto.OutstockUpdateDTO;
import com.xbongbong.pro.outstockproduct.pojo.dto.OutstockProductDeleteBatchDTO;
import com.xbongbong.pro.outstockproduct.pojo.vo.OutstockProductDeleteBatchVO;
import com.xbongbong.pro.product.pojo.dto.CostRecalculationDTO;
import com.xbongbong.pro.rabbitmq.producer.BaseProducer;
import com.xbongbong.pro.rabbitmq.producer.CostRecalculationProducer;
import com.xbongbong.pro.returnedpurchase.pojo.dto.ReturnedPurchaseUpdateBatchDTO;
import com.xbongbong.pro.returnedpurchase.pojo.dto.ReturnedPurchaseUpdateDTO;
import com.xbongbong.pro.thread.ThreadPoolBeanConfig;
import com.xbongbong.pro.transfer.pojo.dto.TransferResetInstockIdDTO;
import com.xbongbong.pro.workorder.pojo.dto.WorkOrderRestoreOutboundDTO;
import com.xbongbong.saas.analytical.impl.OutstockValidateAnalyticalServiceImpl;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.ErrorMessageConstant;
import com.xbongbong.saas.constant.MultiUnitConstant;
import com.xbongbong.saas.constant.ParameterConstant;
import com.xbongbong.saas.constant.ProductConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.domain.entity.BatchFlowBillUpdateEntity;
import com.xbongbong.saas.domain.entity.BusinessProductEntity;
import com.xbongbong.saas.domain.entity.OutstockProductEntity;
import com.xbongbong.saas.domain.entity.ProductStockUpdateEntity;
import com.xbongbong.saas.domain.entity.ProductWarehouseEntity;
import com.xbongbong.saas.domain.entity.ReturnedPurchaseProductEntity;
import com.xbongbong.saas.domain.entity.SettleAccountsEntity;
import com.xbongbong.saas.domain.entity.StockFlowBillUpdateEntity;
import com.xbongbong.saas.domain.entity.ext.ContractEntityExt;
import com.xbongbong.saas.domain.entity.ext.CustomerEntityExt;
import com.xbongbong.saas.domain.entity.ext.OutstockEntityExt;
import com.xbongbong.saas.enums.InstockTypeEnum;
import com.xbongbong.saas.enums.OperateModuleTypeEnum;
import com.xbongbong.saas.enums.OperateTypeEnum;
import com.xbongbong.saas.enums.OutstockTypeEnum;
import com.xbongbong.saas.enums.RedundantTemplateTypeEnum;
import com.xbongbong.saas.enums.ReturnedPurchaseStatusEnum;
import com.xbongbong.saas.enums.SelectProductEnum;
import com.xbongbong.saas.enums.StockTypeEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.ContractEnum;
import com.xbongbong.saas.enums.business.ContractOutstockEnum;
import com.xbongbong.saas.enums.business.CustomerManagementEnum;
import com.xbongbong.saas.enums.business.InstockEnum;
import com.xbongbong.saas.enums.business.InventoryEnum;
import com.xbongbong.saas.enums.business.OrderEnum;
import com.xbongbong.saas.enums.business.OrderOutStockEnum;
import com.xbongbong.saas.enums.business.OutstockEnum;
import com.xbongbong.saas.enums.business.ProductEnum;
import com.xbongbong.saas.enums.business.ProductionOrderEnum;
import com.xbongbong.saas.enums.business.ReturnedPurchaseEnum;
import com.xbongbong.saas.enums.business.ReturnedPurchaseOutstockEnum;
import com.xbongbong.saas.enums.business.TransferEnum;
import com.xbongbong.saas.enums.business.WorkOrderEnum;
import com.xbongbong.saas.enums.business.WorkOrderOutstockEnum;
import com.xbongbong.saas.enums.dictionary.OrderStatusEnum;
import com.xbongbong.saas.enums.dictionary.ReturnedStatusEnum;
import com.xbongbong.saas.enums.product.ContractOutstockProductEnum;
import com.xbongbong.saas.enums.product.InstockProductEnum;
import com.xbongbong.saas.enums.product.OutstockProductEnum;
import com.xbongbong.saas.enums.subform.ProductWarehouseSubFormEnum;
import com.xbongbong.saas.help.BatchSeqExplainHelp;
import com.xbongbong.saas.help.DefaultAttrHelp;
import com.xbongbong.saas.help.ExplainHelp;
import com.xbongbong.saas.help.LogHandleHelp;
import com.xbongbong.saas.help.ReceivablesHelper;
import com.xbongbong.saas.help.SaasDeleteHelp;
import com.xbongbong.saas.help.SaasSaveHelp;
import com.xbongbong.saas.help.SaasUpdateHelp;
import com.xbongbong.saas.model.ContractModel;
import com.xbongbong.saas.model.CustomerModel;
import com.xbongbong.saas.model.CustomerUserModel;
import com.xbongbong.saas.model.LinkProductRelyModel;
import com.xbongbong.saas.model.OutstockModel;
import com.xbongbong.saas.model.OutstockProductModel;
import com.xbongbong.saas.model.ReturnedPurchaseProductModel;
import com.xbongbong.saas.model.SettleAccountsModel;
import com.xbongbong.saas.service.BatchFlowBillService;
import com.xbongbong.saas.service.BusinessProductService;
import com.xbongbong.saas.service.ContractService;
import com.xbongbong.saas.service.FundSetService;
import com.xbongbong.saas.service.InventoryService;
import com.xbongbong.saas.service.OrderOutstockService;
import com.xbongbong.saas.service.OriStockService;
import com.xbongbong.saas.service.OutstockProductService;
import com.xbongbong.saas.service.OutstockService;
import com.xbongbong.saas.service.PaymentService;
import com.xbongbong.saas.service.ProductSerialService;
import com.xbongbong.saas.service.ProductService;
import com.xbongbong.saas.service.ProductionOrderService;
import com.xbongbong.saas.service.ReturnedPurchaseService;
import com.xbongbong.saas.service.StockFlowBillService;
import com.xbongbong.saas.service.TransferService;
import com.xbongbong.saas.service.WorkOrderService;
import com.xbongbong.saas.service.toolbox.help.LogHelp;
import com.xbongbong.saas.service.toolbox.help.ProductHelp;
import com.xbongbong.saas.toolbox.help.FastJsonHelper;
import com.xbongbong.sys.domain.entity.DepartmentEntity;
import com.xbongbong.sys.domain.entity.UserEntity;
import com.xbongbong.sys.model.CompanyConfigModel;
import com.xbongbong.sys.model.UserModel;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.action.support.WriteRequest;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
import static org.elasticsearch.index.query.QueryBuilders.termQuery;
import static org.elasticsearch.index.query.QueryBuilders.termsQuery;

/**
 * @author chaoxiong.lei
 * @date 2019/1/20 19:10
 */
@Service("OrderOutstockService")
public class OrderOutstockServiceImpl implements OrderOutstockService {

    private static final Logger LOG = LoggerFactory.getLogger(OrderOutstockServiceImpl.class);

    @Resource
    private SaasSaveHelp saasSaveHelp;
    @Resource
    private SaasUpdateHelp saasUpdateHelp;
    @Resource
    private ExplainHelp explainHelp;
    @Resource
    private DefaultAttrHelp defaultAttrHelp;
    @Resource
    private OutstockProductModel outstockProductModel;
    @Resource
    private OutstockModel outstockModel;
    @Resource
    private ContractService contractService;
    @Resource
    private ContractModel contractModel;
    @Resource
    private OutstockProductService outstockProductService;
    @Resource
    private ReturnedPurchaseService returnedPurchaseService;
    @Resource
    private InventoryService inventoryService;
    @Resource
    private TransferService transferService;
    @Resource
    private ProductionOrderService productionOrderService;
    @Resource
    private ProductService productService;
    @Resource
    private CustomerUserModel customerUserModel;
    @Resource
    private BusinessProductService businessProductService;
    @Resource
    private UserModel userModel;
    @Resource
    private BaseProducer baseProducer;
    @Resource
    private ReturnedPurchaseProductModel returnedPurchaseProductModel;
    @Resource
    private WorkOrderService workOrderService;
    @Resource
    private EsHelper esHelper;
    @Resource
    private ThreadPoolBeanConfig threadPoolBeanConfig;
    @Resource
    private MongoLogHelp mongoLogHelp;
    @Resource
    private FormDataValidateProductHelp formDataValidateProductHelp;
    @Resource
    private PaasFormExplainModel paasFormExplainModel;
    @Resource
    private ProductHelp productHelp;
    @Resource
    private CustomerModel customerModel;
    @Resource
    private PaasEsModel paasEsModel;
    @Resource
    private LinkProductRelyModel linkProductRelyModel;
    @Resource
    private FormDataUpdateGetAnalysisDataHelp formDataUpdateGetAnalysisDataHelp;
    @Resource
    private ProFormHelp proFormHelp;
    @Resource
    private UserHelp userHelp;
    @Resource
    private PaasRedisHelper paasRedisHelper;
    @Resource
    SaasDeleteHelp saasDeleteHelp;
    @Resource
    private ProductSerialService productSerialService;
    @Resource
    private StockFlowBillService stockFlowBillService;
    @Resource
    private CompanyConfigModel companyConfigModel;
    @Resource
    private OriStockService oriStockService;
    @Resource
    private BatchFlowBillService batchFlowBillService;
    @Resource
    private TransferSubFormHelper transferSubFormHelper;
    @Resource
    private PaasProcessRelatedDataModel paasProcessRelatedDataModel;
    @Resource
    private LogHelp logHelp;
    @Resource
    private OutstockServiceImpl outstockServiceImpl;
    @Resource
    private FundSetService fundSetService;
    @Resource
    private ReceivablesHelper receivablesHelper;
    @Resource
    private PaymentService paymentService;
    @Resource
    private OutstockService outstockService;
    @Resource
    private OutstockValidateAnalyticalServiceImpl outstockAnalyticalService;
    @Resource
    private CommonHelp commonHelp;
    @Resource
    private SettleAccountsModel settleAccountsModel;
    @Resource
    private CostRecalculationProducer costRecalculationProducer;
    @Resource
    private LogHandleHelp logHandleHelp;

    @Override
    public void beforeSave(ValidateDataDTO validateDataDTO) throws XbbException {
        JSONObject data = validateDataDTO.getData();
        Long dataId = validateDataDTO.getDataId();
        Long taskId = validateDataDTO.getTaskId();
        String corpid = validateDataDTO.getCorpid();
        Long date = data.getLong(OutstockEnum.TIME.getAttr());
        if (Objects.isNull(date)) {
            throw new XbbException(OutstockErrorCodeEnum.API_ERROR_212041);
        }
        //结账中校验
        String redisHelperValue = paasRedisHelper.getValue(RedisPrefixConstant.SETTLE_ACCOUNTS, corpid);
        if (StringUtil.isNotEmpty(redisHelperValue)) {
            if (date <= DateTimeUtil.getTodayEndInt(Long.valueOf(redisHelperValue))){
                throw new XbbException(SettleAccountErrorCodeEnum.API_ERROR_254007);
            }
        }
        //获取最近一次结账日期
        SettleAccountsEntity accountsEntity = settleAccountsModel.getLastSettleAccounts(corpid);
        OutstockEntityExt outstockEntityExt = null;
        if (dataId != null && !Objects.equals(dataId, 0L)) {
            //校验日期是否受结账限制
            if (Objects.nonNull(accountsEntity) && Objects.nonNull(accountsEntity.getCheckOutTime())) {
                if (date <= DateTimeUtil.getTodayEndInt(accountsEntity.getCheckOutTime())) {
                    throw new XbbException(OutstockErrorCodeEnum.API_ERROR_212051);
                }
            }
            outstockEntityExt = outstockModel.getByKey(dataId, corpid);
        } else {
            String value = paasRedisHelper.getValue(RedisPrefixConstant.PRODUCE_STOCK_FLOW, corpid);
            if (StringUtil.isNotEmpty(value)) {
                throw new XbbException(OutstockErrorCodeEnum.API_ERROR_212038);
            }
            //获取最近一次结账日期
            //校验日期是否受结账限制
            if (Objects.nonNull(accountsEntity) && Objects.nonNull(accountsEntity.getCheckOutTime())) {
                if (date <= DateTimeUtil.getTodayEndInt(accountsEntity.getCheckOutTime())) {
                    throw new XbbException(OutstockErrorCodeEnum.API_ERROR_212031);
                }
            }
        }
        Integer businessType = validateDataDTO.getBusinessType();
        OutstockTypeEnum outstockTypeEnum;
        Integer type = data.getInteger(OutstockEnum.TYPE.getAttr());
        if (Objects.isNull(type)) {
            outstockTypeEnum = OutstockTypeEnum.getByStockBusinessType(businessType);
            data.put(OutstockEnum.TYPE.getAttr(), String.valueOf(outstockTypeEnum.getCode()));
        }
        //setRefType
        data.put(OutstockEnum.TYPE.getAttr(),String.valueOf(OutstockTypeEnum.CONTRACT_OUTSTOCK.getCode()));
        Map<String, FieldAttrEntity> explainMap = validateDataDTO.getExplainMap();
        // ==============数据格式校验===================
        // 校验编号长度不超过100且编号存在
        FieldAttrEntity fieldAttrEntity = new FieldAttrEntity();
        FieldAttrEntity sheetNo = explainMap.getOrDefault(OutstockEnum.SHEET_NO.getAttr(), fieldAttrEntity);
        saasSaveHelp.checkSerialNumber(validateDataDTO.getSerialNo(), Objects.toString(sheetNo.getAttrName(), ""));

        //批次号保存前必填校验
        saasSaveHelp.batchSaveRequiredCheck(validateDataDTO);

        FieldAttrEntity memoField = explainMap.getOrDefault(OrderOutStockEnum.MEMO.getAttr(), fieldAttrEntity);
        // 校验备注长度
        saasSaveHelp.checkFieldEntityLength(data, OrderOutStockEnum.MEMO.getAttr(), Objects.toString(memoField.getAttrName(), ""), AttrLenthConstant.MEMO_MAX_LENGTH);

        saasSaveHelp.formatLinkBusiness4Save(data, OrderOutStockEnum.WAREHOUSE_ID.getAttr(), OrderOutStockEnum.WAREHOUSE_ID_LINKED_TEXT.getAttr(), OrderOutStockEnum.WAREHOUSE_ID.getFieldType());
        if (data.getJSONArray(OrderOutStockEnum.REF_ID.getAttr()) == null || data.getJSONArray(OrderOutStockEnum.REF_ID.getAttr()).size() == 0) {
            data.remove(OrderOutStockEnum.REF_ID.getAttr());
        }
        saasSaveHelp.formatLinkBusiness4Save(data, OrderOutStockEnum.LINK_PARTNER_RECEIVER.getAttr(), OrderOutStockEnum.LINK_PARTNER_RECEIVER_HIDE.getAttr(), OrderOutStockEnum.LINK_PARTNER_RECEIVER.getFieldType());
        saasSaveHelp.formatLinkBusiness4Save(data, OrderOutStockEnum.SEND_NAME.getAttr(), OrderOutStockEnum.LINK_SEND_HIDE.getAttr(), OrderOutStockEnum.SEND_NAME.getFieldType());
        saasSaveHelp.formatLinkBusiness4Save(data, OrderOutStockEnum.REF_ID.getAttr(), OrderOutStockEnum.REF_ID_LINKED_TEXT.getAttr(), OrderOutStockEnum.REF_ID.getFieldType());
        saasSaveHelp.formatLinkBusiness4Save(data, ContractOutstockEnum.LINK_CUSTOMER.getAttr(), ContractOutstockEnum.LINK_CUSTOMER_HIDE.getAttr(), ContractOutstockEnum.LINK_CUSTOMER.getFieldType());
        // 如果前端没传根据默认公式计算一下
        if (Objects.isNull(data.getDouble(OrderOutStockEnum.TOTAL_MONEY.getAttr()))) {
            JSONArray productArr = data.getJSONArray(ContractOutstockEnum.PRODUCT.getAttr());
            if (CollectionsUtil.isNotEmpty(productArr)) {
                Double productTotal = 0D;
                for (Object product : productArr) {
                    JSONObject productObj = (JSONObject) product;
                    if (Objects.nonNull(productObj.getDouble(SelectProductEnum.SUBTOTAL.getAttr()))) {
                        productTotal += productObj.getDouble(SelectProductEnum.SUBTOTAL.getAttr());
                    }
                }
                data.put(OrderOutStockEnum.TOTAL_MONEY.getAttr(), productTotal);
            } else {
                data.put(OrderOutStockEnum.TOTAL_MONEY.getAttr(), 0);
            }
        }
        if (Arith.compare(data.getDouble(OrderOutStockEnum.TOTAL_MONEY.getAttr()), 0) < 0) {
            throw new XbbException(OutstockErrorCodeEnum.API_ERROR_212042.getCode(), OutstockErrorCodeEnum.API_ERROR_212042.getMsg());
        }
        if (Objects.isNull(data.getDouble(OrderOutStockEnum.DISCOUNT_AMOUNT.getAttr()))) {
            data.put(OrderOutStockEnum.DISCOUNT_AMOUNT.getAttr(), 0);
        }
        Long orderId = Long.parseLong(data.get(OrderOutStockEnum.REF_ID.getAttr()).toString());
        ContractEntityExt contractEntityExt = contractModel.getByKey(orderId, corpid);
        Double orderMoney = contractEntityExt.getData().getDouble(OrderEnum.AMOUNT.getAttr());
        PaasFormDataEsListVO orderOutstockListVO = outstockService.getOutstockListFromEs(corpid, orderId, OutstockTypeEnum.CONTRACT_OUTSTOCK.getCode(), validateDataDTO.getDistributorMark());
        double orderOutstockTotalMoney = outstockService.getContractOutstockTotalMoney(data, dataId, orderOutstockListVO);
        // 当按出库产生应收时,和订货单金额比较
        Long modelType = fundSetService.getModelType(corpid,XbbRefTypeEnum.CRM);
        if (Objects.equals(modelType, ModelTypeEnum.OUTSTOCK.getCode())) {
            if(Objects.nonNull(orderMoney) && Arith.compare(orderOutstockTotalMoney, orderMoney) > 0){
                throw new XbbException(OutstockErrorCodeEnum.API_ERROR_212043.getCode(), OutstockErrorCodeEnum.API_ERROR_212043.getMsg());
            }
            // 合同数据
            JSONObject contractEntityExtData = contractEntityExt.getData();
            JSONArray outstockIdList = contractEntityExtData.getJSONArray(ContractEnum.OUTSTOCK_ID.getAttr());
            List<Long> outstockIds = new ArrayList<>();
            if (CollectionsUtil.isNotEmpty(outstockIdList)) {
                for (int i = 0; i < outstockIdList.size(); i++) {
                    Long outstockId = outstockIdList.getLong(i);
                    if (!Objects.equals(outstockId, dataId)) {
                        outstockIds.add(outstockId);
                    }
                }
            }
            // 优惠金额
            String discountAmountAttr = OrderOutStockEnum.DISCOUNT_AMOUNT.getAttr();
            // 合同已出库优惠金额
            BigDecimal contractOutstockDiscountAmount = BigDecimal.ZERO;
            if (CollectionsUtil.isNotEmpty(outstockIds)) {
                List<OutstockEntityExt> outstockEntityExts = outstockModel.listInId(corpid, outstockIds);
                List<JSONObject> outstockDataList = outstockEntityExts.stream().map(OutstockEntityExt::getData).collect(Collectors.toList());
                for (JSONObject outstockData : outstockDataList) {
                    if (outstockData.containsKey(discountAmountAttr)) {
                        contractOutstockDiscountAmount = contractOutstockDiscountAmount.add(outstockData.getBigDecimal(discountAmountAttr));
                    }
                }
            }
            if(data.containsKey(discountAmountAttr) && Objects.nonNull(contractEntityExtData.get(discountAmountAttr))){
                // 以出库优惠金额 = 合同已出库优惠金额 + 销售出库单存在优惠金额
                BigDecimal outstockDiscountAmount = contractOutstockDiscountAmount.add(data.getBigDecimal(discountAmountAttr));
                // 当以出库优惠金额大于合同优惠金额则抛出异常
                if (outstockDiscountAmount.compareTo(contractEntityExtData.getBigDecimal(ContractEnum.DISCOUNT_AMOUNT.getAttr())) > 0){
                    throw new XbbException(OutstockErrorCodeEnum.API_ERROR_212050.getCode(), OutstockErrorCodeEnum.API_ERROR_212050.getMsg());
                }
            }
        }
        // ==============业务逻辑校验===================
        // 出库单特殊逻辑校验
        // 注意：这里的校验是基于上面关联业务校验之后做的，data格式已经和前端传入的不同，不能和formatLinkBusiness4Save调换顺序
        outstockAnalyticalService.checkOutstock(data, outstockEntityExt);
        boolean isNew = dataId == null || Objects.equals(dataId, 0L);
        if (isNew) {
            // 新建时出库单产品校验。编辑时不校验，因为编辑时不能修改产品
            outstockAnalyticalService.checkOutstockProduct2(data, corpid, dataId, taskId, true);
            // 校验上有单据是否关闭 关闭则不允许审批通过
            if (Objects.nonNull(taskId) && taskId > BasicConstant.ZERO){
                ContractEntityExt orderExt = contractModel.getByKey(data.getLong(OrderOutStockEnum.REF_ID.getAttr()), corpid);
                JSONObject orderData = orderExt.getData();
                if(Objects.nonNull(orderData)){
                    Object orderStatus = orderData.get(OrderEnum.STATUS.getAttr());
                    if (Objects.equals(OrderStatusEnum.CLOSED.getCode(),orderStatus)){
                        throw new XbbException(OutstockErrorCodeEnum.API_ERROR_212046);
                    }
                }

            }

        }
        validateDataDTO.setData(data);
    }

    @Override
    public void afterSave(SaasFormSaveDTO saasFormSaveDTO) throws XbbException {
//        Integer outbound = saasUpdateHelp.getIntegerFromFormData(data, OutstockEnum.OUTBOUND.getAttr());
        JSONObject data = saasFormSaveDTO.getNewData();
        Integer type = data.getInteger(OutstockEnum.TYPE.getAttr());
        String corpid = saasFormSaveDTO.getCorpid();
        Long refId = Objects.isNull(data.getLong(OutstockEnum.REF_ID.getAttr())) ? 0L : data.getLong(OutstockEnum.REF_ID.getAttr());
        Long contractId = data.getLong(OutstockEnum.REF_ID.getAttr());
        ContractEntityExt contractEntityExt = null;
        if (saasFormSaveDTO.getIsNew()) {
            // 改为新建时进行以下逻辑：产品保存、库存更新、上游单据更新
            // 获取对应数据
            PaasFormDataEntity newEntity = saasFormSaveDTO.getNewPaasFormDataEntity();
            JSONObject dataList = newEntity.getData();
            // 获取关联产品的数据
            JSONArray productJsonArray = dataList.getJSONArray(OutstockEnum.PRODUCT.getAttr());
            String productStr = productJsonArray.toJSONString();
            // 更新出库产品库存
            Long outstockId = newEntity.getId();
            //上游单据id
            Long formId = saasFormSaveDTO.getNewPaasFormDataEntity().getFormId();
            outstockServiceImpl.saveProduct(productJsonArray, corpid, outstockId, type, refId, formId, false);
            // 序列号入库
            productSerialService.saveSerial(saasFormSaveDTO, productStr);
            // 更新上游单据
            outstockServiceImpl.setOutstockDoucmentsNew(saasFormSaveDTO);
            //发送重算参数
            SaasFormSaveDTO saasFormSaveDTOCost = new SaasFormSaveDTO();
            saasFormSaveDTOCost.setCorpid(saasFormSaveDTO.getCorpid());
            saasFormSaveDTOCost.setBusinessType(saasFormSaveDTO.getBusinessType());
            saasFormSaveDTOCost.setNewData(saasFormSaveDTO.getNewData());
            saasFormSaveDTOCost.setNewPaasFormDataEntity(saasFormSaveDTO.getNewPaasFormDataEntity());
            CostRecalculationDTO costRecalculationDTO = new CostRecalculationDTO();
            costRecalculationDTO.setData(data);
            costRecalculationDTO.setMark(BasicConstant.ONE);
            costRecalculationDTO.setType(StockTypeEnum.OUT_STOCK.getCode());
            costRecalculationDTO.setCorpid(corpid);
            costRecalculationDTO.setStockId(outstockId);
            costRecalculationDTO.setIsWorkFlow(BasicConstant.ONE);
            costRecalculationDTO.setSaasFormSaveDTO(saasFormSaveDTOCost);
            //将流水放至重算方法中生成，保证处理的先后顺序
            /*stockFlowBillService.caculateStockModification4Save(saasFormSaveDTO);
            batchFlowBillService.batchFlowModification4Save(saasFormSaveDTO);*/
            costRecalculationProducer.sendMessage(costRecalculationDTO);
            if (saasFormSaveDTO.getIsNew() && Objects.equals(type, OutstockTypeEnum.CONTRACT_OUTSTOCK.getCode())) {
                //获取当前处于什么模式
                Long modelType = fundSetService.getModelType(corpid,XbbRefTypeEnum.CRM);
                if(Objects.equals(modelType, ModelTypeEnum.OUTSTOCK.getCode())){
                    receivablesHelper.createReceivablesHandle(saasFormSaveDTO, modelType, null);
                }
                // 销售出库消息推送
                Runnable runnable = () -> {
                    try {
                        PaasFormDataEntityExt contractFormDataEntity = contractModel.getByKey(refId, corpid);
                        if (Objects.nonNull(contractFormDataEntity)) {
                            Long customerId = contractFormDataEntity.getData().getLong(ContractEnum.LINK_CUSTOMER.getAttr());
                            //客户负责人
                            List<String> customerUserList = customerUserModel.getCustomerUserIdList(corpid, Collections.singletonList(customerId), null);
                            if (customerUserList == null) {
                                customerUserList = new ArrayList<>();
                            }
                            //合同创建人
                            customerUserList.add(contractFormDataEntity.getCreatorId());
                            //推送给仓库主管
                            List<UserEntity> managers = userModel.getUsersByRoleId(corpid, Collections.singletonList(22));
                            for (UserEntity manager : managers) {
                                customerUserList.add(manager.getUserId());
                            }
                            PushRefTypePojo.Options options = new PushRefTypePojo.Options(contractFormDataEntity.getAppId(), contractFormDataEntity.getMenuId(), contractFormDataEntity.getFormId(), refId, Collections.singletonList(refId), SaasMarkEnum.SAAS.getCode(), XbbRefTypeEnum.CONTRACT.getCode(), XbbRefTypeEnum.CONTRACT.getCode());
                            MessageRabbitMqDTO messageRabbitMqDTO = new MessageRabbitMqDTO(saasFormSaveDTO.getCorpid(), customerUserList, Collections.singletonList(refId), 0, null, I18nMessageUtil.getMessage(OutstockPushConstant.OUTSTOCK_TITLE), String.format(I18nMessageUtil.getMessage(OutstockPushConstant.ORDER_OUTSTOCK_CONTENT), contractFormDataEntity.getSerialNo()), null, options);
                            baseProducer.sendMessage(PushTypeEnum.OUTSTOCK_SUCCESS_PUSH, messageRabbitMqDTO);
                        }
                    } catch (Exception e) {
                        LOG.error("销售出库消息推送", e);
                    }
                };
                threadPoolBeanConfig.addUpdateDelThreadPool().execute(runnable);
            }
        } else if (Objects.equals(type,OutstockTypeEnum.CONTRACT_OUTSTOCK.getCode())){
            boolean updateExpressName = !Objects.equals(saasFormSaveDTO.getOldData().getString(OutstockEnum.EXPRESS_NAME.getAttr()), data.get(OutstockEnum.EXPRESS_NAME.getAttr()));
            boolean updateExpressNo = !Objects.equals(saasFormSaveDTO.getOldData().getString(OutstockEnum.EXPRESS_NO.getAttr()), data.get(OutstockEnum.EXPRESS_NO.getAttr()));
            // 查询合同数据
            contractEntityExt = contractModel.getByKey(contractId, corpid);
            if (updateExpressName || updateExpressNo) {
                if (updateExpressName) {
                    contractEntityExt.getData().put(ContractEnum.EXPRESS_NAME.getAttr(), data.get(OutstockEnum.EXPRESS_NAME.getAttr()));
                }
                if (updateExpressNo) {
                    contractEntityExt.getData().put(ContractEnum.EXPRESS_NO.getAttr(), data.get(OutstockEnum.EXPRESS_NO.getAttr()));
                }
            }
        }
        contractEntityExt = Objects.nonNull(contractEntityExt) ? contractEntityExt : contractModel.getByKey(contractId, corpid);
        if(Objects.nonNull(contractEntityExt) && MapUtils.isNotEmpty(contractEntityExt.getData()) && contractEntityExt.getData().containsKey(ContractEnum.OUTSTOCK_ID.getAttr())){
            JSONObject contractEntityExtData = contractEntityExt.getData();
            String outstockIdAttr = ContractEnum.OUTSTOCK_ID.getAttr();
            // 获取合同订单的全部出库单ID
            List<Long> outStockIdList = new ArrayList<>();
            JSONArray jsonArray = contractEntityExtData.getJSONArray(outstockIdAttr);
            for (int i = 0; i < jsonArray.size(); i++) {
                outStockIdList.add(jsonArray.getLong(i));
            }
            // 优惠金额
            String discountAmountAttr = OrderOutStockEnum.DISCOUNT_AMOUNT.getAttr();
            List<String> attrs = Collections.singletonList(discountAmountAttr);
            Map<String, BigDecimal> attrSumMap = outstockModel.sumJsonByIdAndAttr(corpid, outStockIdList, attrs);
            contractEntityExtData.put(ContractEnum.OUTSTOCK_DISCOUNT_AMOUNT.getAttr(), attrSumMap.getOrDefault(discountAmountAttr, BigDecimal.ZERO));
            // 更新合同数据
            contractModel.update(contractEntityExt);
        }
    }

    @Override
    public Boolean formatAddExplain(FormatExplainDTO formatExplainDTO) throws XbbException {
        List<FieldAttrEntity> explainList = formatExplainDTO.getExplainList();
        String corpid = formatExplainDTO.getCorpid();
        for (FieldAttrEntity fieldAttrEntity : explainList) {
            Integer fieldType = fieldAttrEntity.getFieldType();
            if (Objects.equals(fieldType, FieldTypeEnum.SELECT_PRODUCT.getType())) {
                fieldAttrEntity.setSupportScanning(BasicConstant.ONE);
                explainHelp.formatSelectProductExplains(fieldAttrEntity, XbbRefTypeEnum.OUTSTOCK, corpid, BasicConstant.ONE, false);
            }
            if (Objects.equals(fieldAttrEntity.getAttr(), OutstockEnum.MANAGER_ID.getAttr())) {
                if(fieldAttrEntity.getDefaultAttr() == null || (fieldAttrEntity.getDefaultAttr() != null && fieldAttrEntity.getDefaultAttr().getDefaultList() == null)) {
                    fieldAttrEntity.setDefaultAttr(defaultAttrHelp.setUserDefaultAttrPoJo(formatExplainDTO.getUserId(), formatExplainDTO.getLoginUser().getName(),formatExplainDTO.getLoginUser().getAvatar()));
                }
            }
            if (!Objects.equals(formatExplainDTO.getEditFormat(), true) && Objects.equals(fieldAttrEntity.getAttr(), OutstockEnum.TYPE.getAttr())) {
                List<ItemPoJo> items = fieldAttrEntity.getItems();
                items.removeIf(item -> Objects.equals(item.getValue(), Objects.toString(OutstockTypeEnum.ASSEMBLE_OUTSTOCK.getCode())));
            }
        }
        return !Objects.equals(formatExplainDTO.getBusinessType(),XbbRefTypeEnum.OTHER_OUTSTOCK.getCode()) || (Objects.nonNull(formatExplainDTO.getLinkBusinessType()));
    }

    @Override
    public DistributorContractOutStockDeleteBatchVO deleteBatch(DistributorContractOutStockDeleteBatchDTO distributorContractOutStockDeleteBatchDTO) throws XbbException {
        DistributorContractOutStockDeleteBatchVO distributorContractOutStockDeleteBatchVO = new DistributorContractOutStockDeleteBatchVO();
        String corpid = distributorContractOutStockDeleteBatchDTO.getCorpid();
        //被锁的入库单id
        List<Long> lackIdList;
        try {
            String limit = paasRedisHelper.getValue(RedisPrefixConstant.PRODUCE_STOCK_FLOW, corpid);
            if (StringUtil.isNotEmpty(limit)) {
                throw new XbbException(OutstockErrorCodeEnum.API_ERROR_212036);
            }
            lackIdList = outstockServiceImpl.checkRedisKey(corpid,distributorContractOutStockDeleteBatchDTO.getDataIdList());
//            if (outstockDeleteBatchDTO.getDataIdList().isEmpty()){
            outstockServiceImpl.lackMsg(lackIdList,corpid);
//            }
            List<Long> outstockIdIn = distributorContractOutStockDeleteBatchDTO.getDataIdList();
            Map<String, Object> param = BeanUtil.convertBean2Map(distributorContractOutStockDeleteBatchDTO, true);
            param.put("idIn", outstockIdIn);
            param.put("del", 0);
            List<OutstockEntityExt> outstockList = outstockModel.findEntitys(param);
            if (Objects.isNull(outstockList) || outstockList.isEmpty()) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
            }
            SettleAccountsEntity accountsEntity = settleAccountsModel.getLastSettleAccounts(corpid);
            for (OutstockEntityExt outstockEntityExt : outstockList) {
                Long date = outstockEntityExt.getData().getLong(OutstockEnum.TIME.getAttr());
                //结账中校验
                String redisHelperValue = paasRedisHelper.getValue(RedisPrefixConstant.SETTLE_ACCOUNTS, corpid);
                if (StringUtil.isNotEmpty(redisHelperValue)) {
                    if (date <= DateTimeUtil.getTodayEndInt(Long.valueOf(redisHelperValue))){
                        throw new XbbException(SettleAccountErrorCodeEnum.API_ERROR_254007);
                    }
                }
                //校验日期是否受结账限制
                if (Objects.nonNull(accountsEntity) && Objects.nonNull(accountsEntity.getCheckOutTime())) {
                    if (date <= DateTimeUtil.getTodayEndInt(accountsEntity.getCheckOutTime())) {
                        throw new XbbException(OutstockErrorCodeEnum.API_ERROR_212032);
                    }
                }
            }
            //库存解绑校验
            outstockServiceImpl.warehouseBoundCheck(outstockList,outstockIdIn,corpid);
            // 出库单删除校验
            //返回值是关闭了批次号管理的产品
            Set<Long> disableBatchProducts = checkOutstockDelete(corpid, outstockList, distributorContractOutStockDeleteBatchDTO.getBusinessType());

            if(!outstockIdIn.isEmpty()) {
                if(BasicConstant.ONE.equals(distributorContractOutStockDeleteBatchDTO.getSingleFlag()) && BasicConstant.ONE.equals(outstockIdIn.size())){
                    outstockModel.deleteByKey(outstockIdIn.get(0),corpid);
                } else {
                    // 出库单ES数据删除等待问题。将刷新策略改为不等待策略，如果后面的代码再次查询出库单列表，则在查询条件中添加【must not in被删除的出库单id列表】的条件
                    outstockModel.deleteBatchImmediately(outstockIdIn, corpid, WriteRequest.RefreshPolicy.NONE);
                }
                distributorContractOutStockDeleteBatchVO.setDeleteIds(outstockIdIn);
            }

            List<Long> returnedPurchaseOutstock = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            List<Long> inventoryOutstock = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            List<Long> transferOutstock = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            List<Long> materielOutstockIdIn = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            Map<Long, OutstockEntityExt> materielOutstockMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            List<OutstockEntityExt> contractOutstockList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            List<OutstockEntityExt> workOrderOutstockList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            List<Long> contractOutstockIdList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            Integer type = null;
            for (OutstockEntityExt item : outstockList) {
                JSONObject jsonObject = item.getData();
                Long refId = jsonObject.getLong(OutstockEnum.REF_ID.getAttr());
                if (Objects.isNull(refId)) {
                    type = OutstockTypeEnum.OTHER_OUTSTOCK.getCode();
                    continue;
                }
                type = jsonObject.getInteger(OutstockEnum.TYPE.getAttr());
                OutstockTypeEnum outstockTypeEnum = OutstockTypeEnum.getByCode(type);
                switch (outstockTypeEnum) {
                    case RETURNED_PURCHASE_OUTSTOCK:
                        returnedPurchaseOutstock.add(refId);
                        break;
                    case CONTRACT_OUTSTOCK:
                        contractOutstockList.add(item);
                        contractOutstockIdList.add(item.getId());
                        break;
                    case INVENTORY_OUTSTOCK:
                        inventoryOutstock.add(refId);
                        break;
                    case TRANSFER_OUTSTOCK:
                        transferOutstock.add(refId);
                        break;
                    case MATERIEL_OUTSTOCK:
                        materielOutstockIdIn.add(refId);
                        // TODO 问题：同一个生产单多次物料出库，则materielOutstockMap会出现相同的refId覆盖数据的情况
                        materielOutstockMap.put(refId, item);
                        break;
                    case WORK_ORDER_OUTSTOCK:
                        workOrderOutstockList.add(item);
                        break;
                    default:
                        break;
                }
            }

            // 删除出库单关联产品
            OutstockProductDeleteBatchDTO outstockProductDeleteBatchDTO = new OutstockProductDeleteBatchDTO();
            BeanUtil.copyProperties(distributorContractOutStockDeleteBatchDTO, outstockProductDeleteBatchDTO);
            outstockProductDeleteBatchDTO.setOutstockIdIn(outstockIdIn);
            OutstockProductDeleteBatchVO outstockProductDeleteBatchVO = outstockProductService.deleteBatchByOutstockIdIn(outstockProductDeleteBatchDTO);
            if (Objects.isNull(outstockProductDeleteBatchVO)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
            }
            List<OutstockProductEntity> outstockProductList = outstockProductDeleteBatchVO.getOutstockProductList();

            // 重置采购退货单关联出库单id
            if (!returnedPurchaseOutstock.isEmpty()) {
                BoolQueryBuilder boolQueryBuilder = boolQuery();
                boolQueryBuilder
                        .filter(termQuery("corpid.keyword", corpid))
                        .filter(termQuery("del", 0))
                        .filter(termsQuery(FieldTypeEnum.DATAID.getAlias(),returnedPurchaseOutstock));
                    List<PaasFormDataEntity> returnedPurchaseEntitys = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_RETURNED_PURCHASE, boolQueryBuilder, PaasFormDataEntity.class, Arrays.asList(FieldTypeEnum.DATAID.getAlias(), ReturnedPurchaseEnum.getAttrConnectData(ReturnedPurchaseEnum.RETURNED_STATUS)));
                    Map<Long,String> returnedPurchaseMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                    returnedPurchaseEntitys.forEach(item -> returnedPurchaseMap.put(item.getDataId(),item.getData().getString(ReturnedPurchaseEnum.RETURNED_STATUS.getAttr())));
                Set<Long> lineReturnedPurchaseIdList = new HashSet<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                List<Long> mergeReturnedPurchaseIdList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                Integer outstockType = null;
                for(OutstockEntityExt outstockEntityExt : outstockList){
                    JSONObject data = outstockEntityExt.getData();
                    outstockType = data.getInteger(OutstockEnum.TYPE.getAttr());
                    if(Objects.equals(outstockType, OutstockTypeEnum.RETURNED_PURCHASE_OUTSTOCK.getCode())){
                        Long outstockId = outstockEntityExt.getId();
                        Long returnedPurchaseId = data.getLong(OutstockEnum.REF_ID.getAttr());
                        for(OutstockProductEntity outstockProductEntity : outstockProductList) {
                            if (Objects.equals(outstockProductEntity.getOutWarehouseId(), outstockId)) {
                                if (!Objects.isNull(outstockProductEntity.getRefProductId())) {
                                    lineReturnedPurchaseIdList.add(returnedPurchaseId);
                                } else {
                                    mergeReturnedPurchaseIdList.add(returnedPurchaseId);
                                }
                            }
                        }
                    }
                }
                List<ReturnedPurchaseUpdateDTO> returnedPurchaseList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                if(!lineReturnedPurchaseIdList.isEmpty()){
                    //新数据修改采购退货产品的已入库数量
                    Set<Long> returnedStatusSet = updateReturnedPurchaseProductOutNumBatch(lineReturnedPurchaseIdList, corpid,outstockIdIn);
                    //出库单删除,对应采购退货单则修改为未出库完成
                    lineReturnedPurchaseIdList.forEach((item)->{
                        ReturnedPurchaseUpdateDTO returnedPurchaseUpdateDTO = new ReturnedPurchaseUpdateDTO();
                        returnedPurchaseUpdateDTO.setId(item);
                        JSONObject data = new JSONObject();
                        // TODO 问题：现在采购退货单可以关联多个采购退货出库单，所以删除一个出库单后并不能将关联关系直接清空，可能还有关联的其他出库单
                        data.put(ReturnedPurchaseEnum.OUTSTOCK_ID.getAttr(), "");
                        data.put(ReturnedPurchaseEnum.STATUS.getAttr(), ReturnedPurchaseStatusEnum.WAIT_OUTSTOCK.getStatus());
                        if (returnedPurchaseMap.containsKey(item)) {
                            String returnedStatus = returnedPurchaseMap.get(item);
                            //先要判断退货状态是否已关闭
                            if (!Objects.equals(returnedStatus, ReturnedStatusEnum.CLOSED.getCode())) {
                                if (returnedStatusSet.contains(item)) {
                                    data.put(ReturnedPurchaseEnum.RETURNED_STATUS.getAttr(),ReturnedStatusEnum.UNRETURNED.getCode());
                                }else {
                                    data.put(ReturnedPurchaseEnum.RETURNED_STATUS.getAttr(),ReturnedStatusEnum.DELIVERED.getCode());
                                }
                            }
                        }
                        returnedPurchaseUpdateDTO.setData(data);
                        returnedPurchaseList.add(returnedPurchaseUpdateDTO);
                    });
                }
                if(!mergeReturnedPurchaseIdList.isEmpty()){
                    BoolQueryBuilder outstockQueryBuilder = boolQuery();
                    outstockQueryBuilder.filter(termQuery("corpid.keyword", corpid));
                    outstockQueryBuilder.filter(termQuery(OutstockEnum.getEsAttr4Keyword(OutstockEnum.TYPE), OutstockTypeEnum.RETURNED_PURCHASE_OUTSTOCK.getCode()));
                    outstockQueryBuilder.filter(termsQuery(OutstockEnum.getEsAttr4Keyword(OutstockEnum.REF_ID), new ArrayList<>(mergeReturnedPurchaseIdList)));
                    outstockQueryBuilder.filter(termQuery(StringConstant.DEL, DelEnum.NORMAL.getDel()));
                    List<PaasFormDataEntityExt> returnPurchaseoutstockList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_OUTSTOCK, outstockQueryBuilder, PaasFormDataEntityExt.class, Arrays.asList(FieldTypeEnum.DATAID.getAlias(), ReturnedPurchaseOutstockEnum.getAttrConnectData(ReturnedPurchaseOutstockEnum.REF_ID)));
                    Set<Long> returnedPurchaseIds = new HashSet<>();
                    //老数据如果查到采购退货单下有其他出库单，则代表部分出库
                    if (!returnPurchaseoutstockList.isEmpty()) {
                        returnPurchaseoutstockList.forEach(item -> returnedPurchaseIds.add(item.getData().getLong(ReturnedPurchaseOutstockEnum.REF_ID.getAttr())));
                    }
                    //旧的数据采购退料单和采购退货出库是一对一
                    mergeReturnedPurchaseIdList.forEach((item)->{
                        ReturnedPurchaseUpdateDTO returnedPurchaseUpdateDTO = new ReturnedPurchaseUpdateDTO();
                        returnedPurchaseUpdateDTO.setId(item);
                        JSONObject data = new JSONObject();
                        data.put(ReturnedPurchaseEnum.OUTSTOCK_ID.getAttr(), "");
                        data.put(ReturnedPurchaseEnum.STATUS.getAttr(), ReturnedPurchaseStatusEnum.WAIT_OUTSTOCK.getStatus());
                        if (returnedPurchaseMap.containsKey(item)) {
                            String returnedStatus = returnedPurchaseMap.get(item);
                            //先要判断退货状态是否已关闭
                            if (!Objects.equals(returnedStatus, ReturnedStatusEnum.CLOSED.getCode())) {
                                if (returnedPurchaseIds.contains(item)) {
                                    data.put(ReturnedPurchaseEnum.RETURNED_STATUS.getAttr(),ReturnedStatusEnum.DELIVERED.getCode());
                                }else {
                                    data.put(ReturnedPurchaseEnum.RETURNED_STATUS.getAttr(),ReturnedStatusEnum.UNRETURNED.getCode());
                                }
                            }
                        }
                        returnedPurchaseUpdateDTO.setData(data);
                        returnedPurchaseList.add(returnedPurchaseUpdateDTO);
                    });
                }
                ReturnedPurchaseUpdateBatchDTO returnedPurchaseUpdateBatchDTO = new ReturnedPurchaseUpdateBatchDTO();
                BeanUtil.copyProperties(distributorContractOutStockDeleteBatchDTO, returnedPurchaseUpdateBatchDTO);
                returnedPurchaseUpdateBatchDTO.setReturnedPurchaseList(returnedPurchaseList);
                returnedPurchaseService.updateBatch(returnedPurchaseUpdateBatchDTO);
            }
            // 盘点出库（重置盘点单关联出库单id）
            if (!inventoryOutstock.isEmpty()) {
                InventoryResetOutstockIdDTO outstockIdDTO = new InventoryResetOutstockIdDTO();
                BeanUtil.copyProperties(distributorContractOutStockDeleteBatchDTO, outstockIdDTO);
                outstockIdDTO.setIdIn(inventoryOutstock);
                outstockIdDTO.setAttr(InventoryEnum.OUTSTOCK_ID.getAttr());
                //一个盘点单下面最多关联一个盘亏出库单，所以删除盘亏出库单时，只要修改盘点单的出库单id字段为0即可。
                inventoryService.resetOutstockIdByIdIn(outstockIdDTO);
            }
            // 调拨出库（重置调拨单关联出库单id）
            if (!transferOutstock.isEmpty()) {
                TransferResetInstockIdDTO resetInstockIdDTO = new TransferResetInstockIdDTO();
                BeanUtil.copyProperties(distributorContractOutStockDeleteBatchDTO, resetInstockIdDTO);
                resetInstockIdDTO.setIdIn(transferOutstock);
                resetInstockIdDTO.setAttr(TransferEnum.OUTSTOCK_ID.getAttr());
                transferService.updateTransferOutstockNum(transferOutstock,corpid,null,false);
                transferService.resetInstockIdByIdIn(resetInstockIdDTO);
            }
            // 生产物料出库（将生产单的关联出库单对应的id删除）
            if (!materielOutstockIdIn.isEmpty()) {
                RetMaterielListDTO retMaterielListDTO = new RetMaterielListDTO();
                BeanUtil.copyProperties(distributorContractOutStockDeleteBatchDTO, retMaterielListDTO);
                retMaterielListDTO.setMaterielOutstockMap(materielOutstockMap);
                retMaterielListDTO.setOutstockIdIn(materielOutstockIdIn);
                retMaterielListDTO.setProductionOrderProductList(outstockProductList);
                // TODO 问题：多次循环内查询
                productionOrderService.updateReturnedMaterielInstock(new InstockProductDeleteBatchVO(),retMaterielListDTO,OutstockTypeEnum.MATERIEL_OUTSTOCK.getStockBusinessType());
            }
            // 更改合同出库状态 及订货单状态
            if (!contractOutstockList.isEmpty()) {
                //判断销售出库单/出库发货单是否有关联应收，并且应收是否有回款单
                List<PaasFormDataEntityExt> paymentList = paymentService.checkCanDelPayment(corpid, ModelTypeEnum.OUTSTOCK.getXbbRefTypeEnum(), contractOutstockIdList);
                if (!CollectionsUtil.isEmpty(paymentList)) {
                    List<Long> errorDataId = new ArrayList<>();
                    List<String> errorDataNo = new ArrayList<>();
                    Set<String> errorTypeSet = new HashSet<>();
                    List<PaasFormDataEntityExt> receivablesEntityExt = receivablesHelper.checkReceivablesWhetherCanDel(paymentList, corpid, errorDataId, errorDataNo, errorTypeSet);
                    if (CollectionsUtil.isEmpty(errorDataId)) {
                        OperateTypeEnum operateTypeEnum = OperateTypeEnum.DELETE;
                        if (Objects.equals(1, distributorContractOutStockDeleteBatchDTO.getIsBusinessRule())) {
                            operateTypeEnum = OperateTypeEnum.RULE_DELETE;
                        }
                        receivablesHelper.delReceivablesHandle(receivablesEntityExt, operateTypeEnum, distributorContractOutStockDeleteBatchDTO.getUserId(), distributorContractOutStockDeleteBatchDTO.getLoginUserName(), corpid, distributorContractOutStockDeleteBatchDTO.getHttpHeader());
                    } else {
                        throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001.getCode(), I18nMessageUtil.getMessage(ErrorMessageConstant.RECEIVABLES_HAS_PAYMENT_SHEET));
                    }
                }
                List<OutstockEntityExt> newContractOutstockList = new ArrayList<>(contractOutstockList.size());
                List<OutstockEntityExt> oldContractOutstockList = new ArrayList<>(contractOutstockList.size());
                // 修改合同表数据集合
                List<UpdateDataEntity> updateDataEntityList = new ArrayList<>(contractOutstockList.size());
                for (OutstockEntityExt outstockEntityExt : contractOutstockList) {
                    boolean isOldContract = false;
                    for (OutstockProductEntity outstockProductEntity : outstockProductList) {
                        if (Objects.equals(outstockEntityExt.getId(), outstockProductEntity.getOutWarehouseId())) {
                            if (outstockProductEntity.getRefProductId() == null) {
                                // 一个销售出库单下只要有一个ref_product_id值为空,则视为老数据，不做行对应
                                isOldContract = true;
                                break;
                            }
                        }
                    }
                    if (isOldContract) {
                        oldContractOutstockList.add(outstockEntityExt);
                    } else {
                        newContractOutstockList.add(outstockEntityExt);
                    }
                    // 更改合同中已出库优惠金额、其他费用
                    // 销售出库单信息
                    JSONObject outstockEntityExtData = outstockEntityExt.getData();
                    // 合同ID
                    Long contractId = outstockEntityExtData.getLong(ContractOutstockEnum.REF_ID.getAttr());
                    // 根据合同ID和公司ID查询合同信息
                    ContractEntityExt contractEntityExt = contractModel.getByKey(contractId, corpid);
                    // 合同信息
                    JSONObject contractEntityExtData = contractEntityExt.getData();
                    // 跟新合同中出库优惠金额 = 合同中已出库优惠金额 - 销售出库单中优惠金额
                    String outstockDiscountAmountAttr = ContractEnum.OUTSTOCK_DISCOUNT_AMOUNT.getAttr();
                    String discountAmountAttr = ContractEnum.DISCOUNT_AMOUNT.getAttr();
                    if(contractEntityExtData.containsKey(outstockDiscountAmountAttr) && contractEntityExtData.containsKey(discountAmountAttr)){
                        BigDecimal contractOutstockDiscountAmount = contractEntityExtData.getBigDecimal(ContractEnum.OUTSTOCK_DISCOUNT_AMOUNT.getAttr());
                        BigDecimal outstockDiscountAmount = outstockEntityExtData.getBigDecimal(ContractOutstockEnum.DISCOUNT_AMOUNT.getAttr());
                        contractEntityExtData.put(ContractEnum.OUTSTOCK_DISCOUNT_AMOUNT.getAttr(), contractOutstockDiscountAmount.subtract(outstockDiscountAmount));
                        updateDataEntityList.add(ExplainUtil.getUpdateData(contractId, contractEntityExtData, corpid));
                    }
                }
                // 更新合同数据
                // 下面那个更新合同数据不知道如何整合为一个，望高人改之。
                contractModel.updateBatch(updateDataEntityList, corpid);
                ContractRestoreOutboundDTO contractRestoreOutboundDTO = new ContractRestoreOutboundDTO();
                BeanUtil.copyProperties(distributorContractOutStockDeleteBatchDTO, contractRestoreOutboundDTO);
                contractRestoreOutboundDTO.setNewContractOutstockList(newContractOutstockList);
                contractRestoreOutboundDTO.setOldContractOutstockList(oldContractOutstockList);
                contractRestoreOutboundDTO.setDelOutstockIdList(outstockIdIn);
                contractService.restoreNewContractOutboundAndStatus(contractRestoreOutboundDTO);
            }
            // 更新工单状态
            if (!workOrderOutstockList.isEmpty()) {
                WorkOrderRestoreOutboundDTO workOrderRestoreOutboundDTO = new WorkOrderRestoreOutboundDTO();
                BeanUtil.copyProperties(distributorContractOutStockDeleteBatchDTO, workOrderRestoreOutboundDTO);
                workOrderRestoreOutboundDTO.setWorkOrderOutstockList(workOrderOutstockList);
                workOrderRestoreOutboundDTO.setWorkOrderProductList(outstockProductList);
                workOrderRestoreOutboundDTO.setDelOutstockIdList(outstockIdIn);
                workOrderService.restoreOutboundAndStatus(workOrderRestoreOutboundDTO);
            }

            List<Long> childProductIdList = new ArrayList<>();
            childProductIdList.add(-1L);
            Set<Long> warehouseIdList = new HashSet<>();
            for (OutstockProductEntity entity : outstockProductList) {
                if(entity != null && entity.getProductId() != null){
                    childProductIdList.add(entity.getProductId());
                }
                warehouseIdList.add(entity.getWarehouseId());
            }
            try {
                // 更新批次库存 分仓库存 产品库存
                Map<Long, ProductStockUpdateEntity> productAddMap = outstockProductService.delUpdateStock(outstockProductList, corpid, disableBatchProducts);
//                productService.updateProductStockDown(new HashMap<>(16), childProductIdList,productMap,corpid,true, false);
                productService.updateProductStock(productAddMap,corpid);
                List<StockFlowBillUpdateEntity> stockFlowBillUpdateList = new ArrayList<>();
                List<BatchFlowBillUpdateEntity> batchFlowBillUpdateEntityList = new ArrayList<>();
                Map<Long, Long> timeMap = new HashMap<>(outstockList.size());
                outstockList.forEach(item -> {
                    timeMap.put(item.getId(), item.getData().getLong(OutstockEnum.TIME.getAttr()));
                });
                List<Long> batchOutStockIdIn = new ArrayList<>();
                outstockProductList.forEach(item -> {
                    StockFlowBillUpdateEntity stockFlowBillUpdateEntity = new StockFlowBillUpdateEntity(item.getProductId() + "_" + item.getWarehouseId(), item.getProductNum(),Arith.mul(item.getProductNum(), item.getCost()), timeMap.get(item.getOutWarehouseId()), DateTimeUtil.getInt(), item.getOutWarehouseId());
                    stockFlowBillUpdateList.add(stockFlowBillUpdateEntity);
                    if (StringUtil.isNotEmpty(item.getBatch()) && !disableBatchProducts.contains(item.getParentId())) {
                        BatchFlowBillUpdateEntity batchFlowBillUpdateEntity = new BatchFlowBillUpdateEntity(item.getProductId() + "_" + item.getWarehouseId() + "_" + item.getBatch() + "_" + item.getProduceDate() + "_" + item.getGuaranteePeriod(), Arith.sub(0D, item.getProductNum()),Arith.mul(Arith.sub(0D, item.getProductNum()), item.getCost()), timeMap.get(item.getOutWarehouseId()), DateTimeUtil.getInt(), item.getOutWarehouseId());
                        batchFlowBillUpdateEntityList.add(batchFlowBillUpdateEntity);
                        batchOutStockIdIn.add(item.getOutWarehouseId());
                    }
                });
                CostRecalculationDTO costRecalculationDTO = new CostRecalculationDTO();
                costRecalculationDTO.setCorpid(corpid);
                costRecalculationDTO.setType(StockTypeEnum.OUT_STOCK.getCode());
                costRecalculationDTO.setMark(BasicConstant.TWO);
                costRecalculationDTO.setOutstockList(outstockList);
                costRecalculationDTO.setStockIdIn(outstockIdIn);
                costRecalculationDTO.setIsWorkFlow(BasicConstant.ONE);
                costRecalculationDTO.setOutstockProductList(outstockProductList);
                costRecalculationDTO.setBatchOutStockIdIn(batchOutStockIdIn);
                costRecalculationDTO.setStockFlowBillUpdateList(stockFlowBillUpdateList);
                costRecalculationDTO.setBatchFlowBillUpdateEntityList(batchFlowBillUpdateEntityList);
                /*stockFlowBillService.caculateStockModification4Delete(outstockIdIn, stockFlowBillUpdateList, XbbRefTypeEnum.OUTSTOCK.getCode(), corpid);
                batchFlowBillService.batchFlowModification4Delete(batchOutStockIdIn, batchFlowBillUpdateEntityList, XbbRefTypeEnum.OUTSTOCK.getCode(), corpid);*/
                oriStockService.reSetWarehouseOriStock(corpid,warehouseIdList);
                costRecalculationProducer.sendMessage(costRecalculationDTO);
            } catch (XbbException e) {
                LOG.error("生成出库单产品出错",e);
            }

            final Integer outstockType = type;
            if (Objects.isNull(outstockType)){
                LOG.error("outstockDelErr:" + JSONObject.toJSONString(distributorContractOutStockDeleteBatchDTO));
                LOG.error("outstockDelErrLen:" + outstockList.size());
            }
            Runnable runnable = () -> {
                try {
                    //查询编号
                    Map<Long, String> outstockIdAndno = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                    for (OutstockEntityExt entityExt : outstockList) {
                        Long outstockId = entityExt.getId();
                        String sheetNo = entityExt.getSerialNo();
                        outstockIdAndno.put(outstockId, sheetNo);
                    }

                    //产品分仓库存数据
                    BoolQueryBuilder boolQueryBuilder = boolQuery();
                    boolQueryBuilder.filter(termQuery("corpid.keyword", corpid));
                    boolQueryBuilder.filter(termsQuery(ProductWarehouseSubFormEnum.getEsAttr(ProductWarehouseSubFormEnum.PRODUCT_ID), childProductIdList));
                    boolQueryBuilder.filter(termQuery(StringConstant.DEL, DelEnum.NORMAL.getDel()));
                    boolQueryBuilder.filter(termQuery(ProductWarehouseSubFormEnum.getEsAttr(ProductWarehouseSubFormEnum.WAREHOUSE_CHECKED), 1));
                    List<String> productWarehouseFieldList = new ArrayList<>();
                    productWarehouseFieldList.add(ProductWarehouseSubFormEnum.getAttrConnectData(ProductWarehouseSubFormEnum.PRODUCT_ID));
                    productWarehouseFieldList.add(ProductWarehouseSubFormEnum.getEsAttr(ProductWarehouseSubFormEnum.WAREHOUSE_ID));
                    productWarehouseFieldList.add(ProductWarehouseSubFormEnum.getEsAttr(ProductWarehouseSubFormEnum.WAREHOUSE_NAME));
                    productWarehouseFieldList.add(ProductWarehouseSubFormEnum.getEsAttr(ProductWarehouseSubFormEnum.NUM));
                    // 这次查询主要是为了用于日志信息记录，考虑线程处理不影响主业务
                    List<PaasFormDataEntity> childProductList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_PRODUCT_WAREHOUSE, boolQueryBuilder, PaasFormDataEntity.class, productWarehouseFieldList);
                    List<ProductWarehouseEntity> productWarehouseEntities = transferSubFormHelper.transferFormDataToProductWarehouseList(childProductList);

                    Map<String, ProductWarehouseEntity> outstockProductStockMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                    productWarehouseEntities.forEach(entityExt -> {
                        String key = entityExt.getProductId() + "_" + entityExt.getWarehouseId();
                        outstockProductStockMap.put(key, entityExt);
                    });

                    // 出库单一对多产品
                    Map<Long, List<OutstockProductEntity>> outstockIdAndListMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                    ListIterator<OutstockProductEntity> listIterator = outstockProductList.listIterator();
                    while (listIterator.hasNext()) {
                        OutstockProductEntity outstockProduct = listIterator.next();
                        Long outstockId = outstockProduct.getOutWarehouseId();
                        List<OutstockProductEntity> outstockProductEntityList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                        outstockProductEntityList.add(outstockProduct);

                        if (outstockIdAndListMap.get(outstockId) == null) {
                            outstockIdAndListMap.put(outstockId, outstockProductEntityList);
                        } else {
                            outstockProductEntityList.addAll(outstockIdAndListMap.get(outstockId));
                            outstockIdAndListMap.put(outstockId, outstockProductEntityList);
                        }
                    }
                    // 各个出库单对应的出库产品
                    Map<Long, List<String>> outstockListMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                    Iterator<Map.Entry<Long, List<OutstockProductEntity>>> outIterator = outstockIdAndListMap.entrySet().iterator();
                    while (outIterator.hasNext()) {
                        Map.Entry<Long, List<OutstockProductEntity>> entry = outIterator.next();
                        Long outstockId = entry.getKey();
                        List<OutstockProductEntity> outstockProductEntities = entry.getValue();

                        List<String> outProductStrList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                        for (OutstockProductEntity outstockProduct : outstockProductEntities) {
                            Double productNum = outstockProduct.getProductNum() == null ? 0D : outstockProduct.getProductNum();
                            Double cost = outstockProduct.getCost() == null ? 0D : outstockProduct.getCost();

                            String key = outstockProduct.getProductId() + "_" + outstockProduct.getWarehouseId();
                            ProductWarehouseEntity productWarehouseEntity = outstockProductStockMap.get(key);
                            // 拼接产品信息
                            String productName = outstockProduct.getProductName() == null ? "--" : outstockProduct.getProductName();
                            String productNo = outstockProduct.getProductNo() == null ? "--" : outstockProduct.getProductNo();
                            String productSpecification = Objects.equals(outstockProduct.getProductSpecification(), "") ? "--" : outstockProduct.getProductSpecification();
                            productSpecification = productSpecification.replaceAll("[`~!@#$%^&*\",.，。【】“”'‘’()+=|{}'.;'\\[\\]<>/?~@#￥%……&*]|\\s*|\t|\r|\n", "");
                            if (productSpecification.contains(":")) {
                                productSpecification = productSpecification.replace(":", "/");
                            }
                            String warehouseName = productWarehouseEntity == null ? "--" : productWarehouseEntity.getWarehouseName();
                            String batch = Objects.equals(outstockProduct.getBatch(), "") ? "--" : outstockProduct.getBatch();
                            StringBuilder sb = new StringBuilder();
                            sb.append("产品名称：").append(productName).append("，").append("产品编号：").append(productNo).append("，")
                                    .append("规格：").append(productSpecification).append("，").append("仓库：").append(warehouseName).append("，")
                                    .append("出库数量：").append(productNum).append("，").append("成本：").append(cost).append("，")
                                    .append("批次号：").append(batch).append("；<br/>");
                            outProductStrList.add(sb.toString());
                        }
                        outstockListMap.put(outstockId, outProductStrList);
                    }

                    //生成删除日志(区分单个删除和批量删除)
                    String userId = distributorContractOutStockDeleteBatchDTO.getUserId();
                    String userName = distributorContractOutStockDeleteBatchDTO.getLoginUserName();
                    List<String> list = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                    // 出入库单流水号不能为空
                    Iterator<Map.Entry<Long, String>> iterator = outstockIdAndno.entrySet().iterator();
                    while (iterator.hasNext()) {
                        Map.Entry<Long, String> entry = iterator.next();
                        Long key = entry.getKey();
                        String value = outstockIdAndno.get(key);
                        if (outstockListMap.containsKey(key)) {
                            List<String> outstockProductStrList = outstockListMap.get(key);
                            String outstockProductStr = StringUtils.join(outstockProductStrList, "，");
                            StringBuilder sb = new StringBuilder();
                            sb.append(value).append("<br/>").append("（").append(outstockProductStr).append("）");
                            list.add(sb.toString());
                        } else {
                            list.add(value);
                        }
                    }
                    OperateTypeEnum operateTypeEnum = OperateTypeEnum.DELETE;
                    if (Objects.equals(1, distributorContractOutStockDeleteBatchDTO.getIsBusinessRule())) {
                        operateTypeEnum = OperateTypeEnum.RULE_DELETE;
                    }
                    OutstockTypeEnum outstockTypeEnum = OutstockTypeEnum.getByCode(outstockType);
                    String nameStr = StringUtils.join(list, "，<br/>");
                    if (outstockIdIn.size() > 1) {
                        String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_BATCH_DELETE_FORM_DETAIL), userName, XbbRefTypeEnum.getByCode(outstockTypeEnum.getStockBusinessType()).getName(), outstockIdIn.size());
                        List<InfoArrPojo> infoArrPojoList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                        InfoArrPojo infoArrPojo = new InfoArrPojo();
                        infoArrPojo.setTitle(OutstockEnum.SHEET_NO.getAttrName());
                        infoArrPojo.setContent(nameStr);
                        infoArrPojoList.add(infoArrPojo);
                        mongoLogHelp.buildLog4InfoArr(infoArrPojoList, corpid, userId, userName, outstockTypeEnum.getOperateModuleTypeEnum(), operateTypeEnum,
                                "", "", memo, distributorContractOutStockDeleteBatchDTO.getHttpHeader());
                    } else if (Objects.equals(outstockIdIn.size(), 1)) {
                        Long outstockLogId = outstockIdIn.get(0);
                        String outstockLogNo = outstockIdAndno.get(outstockLogId);
                        String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_DELETE_WORK), userName, XbbRefTypeEnum.getByCode(outstockTypeEnum.getStockBusinessType()).getName(), outstockLogNo);
                        List<InfoArrPojo> infoArrPojoList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                        InfoArrPojo infoArrPojo = new InfoArrPojo();
                        infoArrPojo.setTitle(OutstockEnum.PRODUCT.getAttrName());
                        infoArrPojo.setContent(nameStr);
                        infoArrPojoList.add(infoArrPojo);
                        mongoLogHelp.buildLog4InfoArr(infoArrPojoList, corpid, userId, userName, outstockTypeEnum.getOperateModuleTypeEnum(), operateTypeEnum,
                                outstockLogId.toString(), outstockLogNo, memo, distributorContractOutStockDeleteBatchDTO.getHttpHeader());
                    }
                } catch (Exception e) {
                    LOG.error("outstockServiceImpl.deleteBatch 记录日志执行出错：", e);
                }
            };
            threadPoolBeanConfig.addUpdateDelThreadPool().execute(runnable);
        } catch (XbbException e){
            outstockServiceImpl.removeDelLack(distributorContractOutStockDeleteBatchDTO.getDataIdList(),corpid);
            LOG.error("outstockServiceImpl.deleteBatch 执行出错：", e);
            throw e;
        } catch (Exception e) {
            outstockServiceImpl.removeDelLack(distributorContractOutStockDeleteBatchDTO.getDataIdList(),corpid);
            LOG.error("outstockServiceImpl.deleteBatch 执行出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
//        removeDelLack(outstockDeleteBatchDTO.getDataIdList(),corpid);
//        lackMsg(lackIdList,corpid);
        return distributorContractOutStockDeleteBatchVO;
    }

    private Set<Long> checkOutstockDelete(String corpid, List<OutstockEntityExt> outstockList, Integer businessType) throws XbbException {
        List<Long> materialOutstockIdList = new ArrayList<>();
        List<Long> contractOutstockIdList = new ArrayList<>();
        List<Long> assembleIdList = new ArrayList<>();
        List<Long> transferIdList = new ArrayList<>();
        Set<Long> outstockIdList = new HashSet<>();
        Set<String> outstockSerialNo = new HashSet<>();
        Map<Long,String> serialNoMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Map<Long,String> transferSerialNoMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Map<Long, String> outstockToSerialNo = new HashMap<>();
        for (OutstockEntityExt item : outstockList) {
            outstockIdList.add(item.getId());
            outstockToSerialNo.put(item.getId(), item.getSerialNo());
            JSONObject jsonObject = item.getData();
            Integer type = jsonObject.getInteger(OutstockEnum.TYPE.getAttr());
            Long refId = jsonObject.getLong(OutstockEnum.REF_ID.getAttr());
            if (Objects.isNull(refId)) {
                continue;
            }
            if (Objects.equals(type, OutstockTypeEnum.MATERIEL_OUTSTOCK.getCode())) {
                materialOutstockIdList.add(item.getId());
            } else if (Objects.equals(type, OutstockTypeEnum.CONTRACT_OUTSTOCK.getCode())) {
                contractOutstockIdList.add(item.getId());
            } else if (Objects.equals(type, OutstockTypeEnum.ASSEMBLE_OUTSTOCK.getCode())) {
                assembleIdList.add(refId);
            } else if (Objects.equals(type, OutstockTypeEnum.TRANSFER_OUTSTOCK.getCode())) {
                transferIdList.add(refId);
            }
            if (Objects.equals(type, OutstockTypeEnum.TRANSFER_OUTSTOCK.getCode())) {
                transferSerialNoMap.put(refId,item.getSerialNo());
            } else {
                serialNoMap.put(item.getId(),item.getSerialNo());
            }
        }
        //现在删除时全都需要查询产品批次保质期序列号状态
        Map<String,Object> outstockProductParam = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        outstockProductParam.put("outstockIdIn", outstockIdList);
        outstockProductParam.put("corpid", corpid);
        outstockProductParam.put("del", 0);
        List<OutstockProductEntity> outstockProductEntityList = outstockProductModel.findEntitys(outstockProductParam);
        //批次序列号校验
        Set<Long> disableBatchProducts = saasDeleteHelp.checkDocumentDelete(corpid, outstockProductEntityList, null, outstockToSerialNo);

        productSerialService.preCheckDelSerial(new ArrayList<>(outstockIdList), corpid, businessType);

        //需要重置一次outstockIdList给下面的业务用
        outstockIdList = new HashSet<>();
        if (!materialOutstockIdList.isEmpty()) {
            // 查询【生产领料出库单】是否存在下游单据【生产退料入库单】
            for (OutstockProductEntity outstockProductEntity : outstockProductEntityList) {
                if (!materialOutstockIdList.contains(outstockProductEntity.getOutWarehouseId())) {
                    continue;
                }
                if (Objects.nonNull(outstockProductEntity.getInstockNum()) && outstockProductEntity.getInstockNum() > BasicConstant.ZERO) {
                    outstockIdList.add(outstockProductEntity.getOutWarehouseId());
                }
            }
            if (outstockIdList.size() > 0) {
                for (Long outstockId : outstockIdList) {
                    outstockSerialNo.add(serialNoMap.get(outstockId));
                }
                for (OutstockEntityExt outstockEntityExt : outstockList) {
                    if (outstockIdList.contains(outstockEntityExt.getId())) {
                        outstockSerialNo.add(outstockEntityExt.getSerialNo());
                    }
                }
                if (outstockSerialNo.size() > 0) {
                    throw new XbbException(OutstockErrorCodeEnum.API_ERROR_212028, String.format(OutstockErrorCodeEnum.API_ERROR_212028.getMsg(), outstockSerialNo.toString()));
                }
            }
        }
        if (!contractOutstockIdList.isEmpty()) {
            for (OutstockProductEntity outstockProductEntity : outstockProductEntityList) {
                if (!contractOutstockIdList.contains(outstockProductEntity.getOutWarehouseId())) {
                    continue;
                }
                if (Objects.nonNull(outstockProductEntity.getInstockNum()) && outstockProductEntity.getInstockNum() > BasicConstant.ZERO) {
                    outstockIdList.add(outstockProductEntity.getOutWarehouseId());
                }
            }
            if (outstockIdList.size() > 0) {
                for (Long outstockId : outstockIdList) {
                    outstockSerialNo.add(serialNoMap.get(outstockId));
                }
                for (OutstockEntityExt outstockEntityExt : outstockList) {
                    if (outstockIdList.contains(outstockEntityExt.getId())) {
                        outstockSerialNo.add(outstockEntityExt.getSerialNo());
                    }
                }
                if (outstockSerialNo.size() > 0) {
                    throw new XbbException(OutstockErrorCodeEnum.API_ERROR_212029, String.format(OutstockErrorCodeEnum.API_ERROR_212029.getMsg(), outstockSerialNo.toString()));
                }
            }
        }
        if (!assembleIdList.isEmpty()) {
            //装配出库单不可以单独删除，要去删除装配单的时候需要一并删除出入库单
            SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
            BoolQueryBuilder boolQueryBuilder = boolQuery();
            boolQueryBuilder.filter(termQuery("corpid.keyword", corpid));
            boolQueryBuilder.filter(termQuery("del", DelEnum.NORMAL.getDel()));
            boolQueryBuilder.filter(termsQuery(FieldTypeEnum.DATAID.getAlias(), assembleIdList));
            // 设置join_field
            boolQueryBuilder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD, IndexTypeEnum.IDX_SAAS_ASSEMBLE.getType()));
            searchSourceBuilder.query(boolQueryBuilder);
            List<PaasFormDataEntityExt> entityExts = paasEsModel.list(searchSourceBuilder, IndexTypeEnum.IDX_SAAS_ASSEMBLE, null, null, null);
            if (Objects.nonNull(entityExts) && entityExts.size() > 0) {
                throw new XbbException(AssembleErrorCodeEnum.API_ERROR_231019, AssembleErrorCodeEnum.API_ERROR_231019.getMsg());
            }
        }
        if (!transferIdList.isEmpty()) {
            BoolQueryBuilder builder = boolQuery();
            builder.filter(termQuery("corpid.keyword", corpid));
            builder.filter(termQuery(StringConstant.DEL, DelEnum.NORMAL.getDel()));
            builder.filter(termsQuery(InstockEnum.getEsAttr4Keyword(InstockEnum.REF_ID), transferIdList));
            builder.filter(termQuery(InstockEnum.getEsAttr4Keyword(InstockEnum.TYPE), InstockTypeEnum.TRANSFER_INSTOCK.getCode()));
            List<String> fieldList = new ArrayList<>();
            fieldList.add(InstockEnum.getAttrConnectData(InstockEnum.REF_ID));
            List<PaasFormDataEntityExt> entityExtList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_INSTOCK, builder, PaasFormDataEntityExt.class, fieldList);
            List<Long> refIdList = new ArrayList<>();
            for (PaasFormDataEntityExt entityExt : entityExtList) {
                refIdList.add(entityExt.getData().getLong(InstockEnum.REF_ID.getAttr()));
            }
            if (!refIdList.isEmpty()){
                for (Long redId : refIdList) {
                    outstockSerialNo.add(transferSerialNoMap.get(redId));
                }
                throw new XbbException(TransferErrorCodeEnum.API_ERROR_229018, String.format(TransferErrorCodeEnum.API_ERROR_229018.getMsg(),outstockSerialNo));
            }
        }
        return disableBatchProducts;
    }

    /**
     * 更新采购退货产品的出库数量
     *
     * @param returnedPurchaseIds 采购退货单
     * @param corpid 公司id
     * @param delOutstockIdList 当前已经被删除的出库单id
     * @throws XbbException 异常
     */
    public Set<Long> updateReturnedPurchaseProductOutNumBatch(Set<Long> returnedPurchaseIds, String corpid,List<Long> delOutstockIdList) throws XbbException {
        //存放已经没有下游出库单的采购退货单ID
        Set<Long> returnedStatusSet = new HashSet<>();
        if(returnedPurchaseIds.isEmpty()||corpid.isEmpty()){
            return returnedStatusSet;
        }
        BoolQueryBuilder outstockQueryBuilder = boolQuery();
        outstockQueryBuilder.filter(termQuery("corpid.keyword", corpid));
        outstockQueryBuilder.filter(termQuery(OutstockEnum.getEsAttr4Keyword(OutstockEnum.TYPE), OutstockTypeEnum.RETURNED_PURCHASE_OUTSTOCK.getCode()));
        outstockQueryBuilder.filter(termsQuery(OutstockEnum.getEsAttr4Keyword(OutstockEnum.REF_ID), new ArrayList<>(returnedPurchaseIds)));
        outstockQueryBuilder.filter(termQuery(StringConstant.DEL, DelEnum.NORMAL.getDel()));
        outstockQueryBuilder.mustNot(termsQuery(FieldTypeEnum.DATAID.getAlias(), delOutstockIdList));
        List<PaasFormDataEntityExt> outstockList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_OUTSTOCK, outstockQueryBuilder, PaasFormDataEntityExt.class, Collections.singletonList(FieldTypeEnum.DATAID.getAlias()));

        List<Long> outstockIds = new ArrayList<>();
        for (PaasFormDataEntityExt entityExt : outstockList) {
            outstockIds.add(entityExt.getDataId());
        }
        //获取采购退货出库单产品
        Map<String, Object> param = new HashMap<>(16);
        param.put("corpid", corpid);
        param.put("del", DelEnum.NORMAL.getDel());
        param.put("outstockIdIn", outstockIds);
        List<OutstockProductEntity> outstockProductEntities = outstockProductModel.findEntitys(param);

        Map<Long, Double> refProductIdNum = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        for(OutstockProductEntity outstockProductEntity : outstockProductEntities){
            Long key = outstockProductEntity.getData().getLong(BusinessConstant.REF_PRODUCT_ID);
            Double num = refProductIdNum.get(key)==null ? outstockProductEntity.getProductNum() : Arith.add(outstockProductEntity.getProductNum(), refProductIdNum.get(key));
            refProductIdNum.put(key,num);
        }
        List<ReturnedPurchaseProductEntity> returnedPurchaseProducts = returnedPurchaseProductModel.getReturnedPurchaseProductByReturnedPurchaseIdIn(corpid, new ArrayList<>(returnedPurchaseIds));
        for(ReturnedPurchaseProductEntity returnedPurchaseProductEntity : returnedPurchaseProducts){
            if(refProductIdNum.containsKey(returnedPurchaseProductEntity.getId())){
                returnedPurchaseProductEntity.setOutstockNum(refProductIdNum.get(returnedPurchaseProductEntity.getId()));
            }else{
                //下游数据已删除完
                returnedPurchaseProductEntity.setOutstockNum(0D);
                //下游数据删除完，代表该采购退货单未入库
                Long returnPurchaseId = returnedPurchaseProductEntity.getReturnPurchaseId();
                returnedStatusSet.add(returnPurchaseId);
            }
            returnedPurchaseProductEntity.setUpdateTime(DateTimeUtil.getInt());
        }
        returnedPurchaseProductModel.updateBatch(returnedPurchaseProducts,corpid);
        return returnedStatusSet;

    }

    @Override
    public void batchEditAttr(DistributorContractOutStockEditAttrUpdateDTO distributorContractOutStockEditAttrUpdateDTO) throws XbbException {
        try {
            List<OutstockUpdateDTO> transferList = new ArrayList<>();
            distributorContractOutStockEditAttrUpdateDTO.getDataIdList().forEach((item)->{
                OutstockUpdateDTO outstockUpdateDTO = new OutstockUpdateDTO();
                outstockUpdateDTO.setId(item);
                JSONObject data = ProSaveHelp.getBatchUpdateData(distributorContractOutStockEditAttrUpdateDTO.getFieldEditedList());
                outstockUpdateDTO.setData(data);
                transferList.add(outstockUpdateDTO);
            });
            List<OutstockEntityExt> outstockEntityList  = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            if (!transferList.isEmpty()) {
                Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                param.put("corpid", distributorContractOutStockEditAttrUpdateDTO.getCorpid());
                param.put("idIn", distributorContractOutStockEditAttrUpdateDTO.getDataIdList());
                outstockEntityList = outstockModel.findEntitys(param);
                if (Objects.isNull(outstockEntityList)){
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
                }
                OutstockUpdateBatchDTO outstockUpdateBatchDTO = new OutstockUpdateBatchDTO();
                BeanUtil.copyProperties(distributorContractOutStockEditAttrUpdateDTO, outstockUpdateBatchDTO);
                outstockUpdateBatchDTO.setOutstockList(transferList);
                updateBatch(outstockUpdateBatchDTO);
            }

            // 批量编辑日志
            List<String> updataItemList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            List<Long> dataIdList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            for (OutstockEntityExt item : outstockEntityList) {
                dataIdList.add(item.getId());
                String serialNo = item.getSerialNo();
                updataItemList.add(serialNo);
            }
            String updataItem = StringUtils.join(updataItemList, "，");
            String userId = distributorContractOutStockEditAttrUpdateDTO.getUserId();
            String corpid = distributorContractOutStockEditAttrUpdateDTO.getCorpid();
            String loginUserName = distributorContractOutStockEditAttrUpdateDTO.getLoginUserName();
            // 标签特殊处理
            Integer fieldType = distributorContractOutStockEditAttrUpdateDTO.getFieldType();
            Boolean isFieldDependence = distributorContractOutStockEditAttrUpdateDTO.getIsFieldDependence();
            logHelp.analysisLabel(corpid, fieldType, isFieldDependence,distributorContractOutStockEditAttrUpdateDTO.getLogFieldEditedList());

            String changedLogItemsStr = logHandleHelp.getChangedLogItemsStr(distributorContractOutStockEditAttrUpdateDTO.getLogFieldEditedList());
            if(dataIdList.size() > 1 ){
                String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_UPDATE_FORM_DATA_BATCH_ATTR), loginUserName, XbbRefTypeEnum.OUTSTOCK.getName(),
                        changedLogItemsStr, dataIdList.size());
                List<InfoArrPojo> infoArrPojoList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                InfoArrPojo infoArrPojo = new InfoArrPojo();
                infoArrPojo.setTitle(XbbRefTypeEnum.OUTSTOCK.getName());
                infoArrPojo.setContent(updataItem);
                infoArrPojoList.add(infoArrPojo);
                mongoLogHelp.buildLog4InfoArr(infoArrPojoList, corpid, userId, loginUserName, OperateModuleTypeEnum.OUTSTOCK, OperateTypeEnum.EDIT,
                        "", "", memo, distributorContractOutStockEditAttrUpdateDTO.getHttpHeader());
            } else if (Objects.equals(dataIdList.size(), 1)){
                String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_UPDATE_FORM_DATA_ATTR), loginUserName, XbbRefTypeEnum.OUTSTOCK.getName(), updataItem,
                        changedLogItemsStr);
                mongoLogHelp.buildLog(corpid, userId, loginUserName, OperateModuleTypeEnum.OUTSTOCK, OperateTypeEnum.EDIT,
                        dataIdList.get(0).toString(), updataItem, memo, distributorContractOutStockEditAttrUpdateDTO.getHttpHeader());
            }
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOG.error("outstockService.batchEditAttr 执行出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
    }

    @Override
    public void formatLinkAddExplain(HandlerExplainInLinkItemDTO handlerExplainInLinkItemDTO) throws XbbException {
        Long linkDataId = handlerExplainInLinkItemDTO.getLinkDataId();
        PaasFormDataEntityExt paasFormDataEntityExt = handlerExplainInLinkItemDTO.getPaasFormDataEntityExt();
        JSONObject dataList = paasFormDataEntityExt.getData();
        String serialNo = paasFormDataEntityExt.getSerialNo();
        String corpid = handlerExplainInLinkItemDTO.getCorpid();
        handlerExplainInLinkItemDTO.setBusinessType(handlerExplainInLinkItemDTO.getPaasFormExplainEntity().getBusinessType());
        CustomerEntityExt customerEntityExt = null;
        FieldAttrEntity fieldAttr = null;
        if (Objects.equals(handlerExplainInLinkItemDTO.getLinkBusinessType(),XbbRefTypeEnum.CONTRACT.getCode())){
            Long customerId = dataList.getJSONArray(ContractEnum.LINK_CUSTOMER.getAttr()).getJSONObject(0).getLong(BusinessConstant.ID);
            customerEntityExt = customerModel.getByKey(customerId,corpid);
            // 判断客户电话子表单是否启用
            if(Objects.nonNull(customerEntityExt)){
                PaasFormExplainEntity paasFormExplainEntity = paasFormExplainModel.getByFormId(customerEntityExt.getFormId(),corpid);
                if(Objects.nonNull(paasFormExplainEntity) && Objects.equals(paasFormExplainEntity.getDel(), DelEnum.NORMAL.getDel())) {
                    String explains = paasFormExplainEntity.getExplains();
                    if(Objects.nonNull(explains)){
                        Map<String, FieldAttrEntity> explainMap = ExplainUtil.getExplainMap(explains, null);
                        fieldAttr = explainMap.get(CustomerManagementEnum.PHONE.getAttr());
                    }
                }
            }
        } else if (Objects.equals(handlerExplainInLinkItemDTO.getLinkBusinessType(),XbbRefTypeEnum.INVENTORY.getCode()) || Objects.equals(handlerExplainInLinkItemDTO.getLinkBusinessType(),XbbRefTypeEnum.TRANSFER.getCode())){
            // 调拨出库和盘亏出库有单据在审批中就不允许关联新建
            if (commonHelp.isOpenWorkFlow(corpid)) {
                BoolQueryBuilder boolQueryBuilder = boolQuery();
                boolQueryBuilder.filter(termQuery("corpid.keyword", corpid));
                boolQueryBuilder.filter(termQuery(ParameterConstant.DEL, DelEnum.NORMAL.getDel()));
                boolQueryBuilder.filter(termQuery(OutstockEnum.getEsAttr4Keyword(OutstockEnum.REF_ID), linkDataId));
                Integer type = OutstockTypeEnum.getByBuisenssTypeInt(handlerExplainInLinkItemDTO.getLinkBusinessType());
                boolQueryBuilder.filter(termQuery(OutstockEnum.getEsAttr4Keyword(OutstockEnum.TYPE), type));
                boolQueryBuilder.filter(termsQuery("flowStatus", Arrays.asList(FlowStatusEnum.APPROVAL_PENDING.getType(), FlowStatusEnum.IN_APPROVAL.getType())));
                long count = paasEsModel.count(boolQueryBuilder, IndexTypeEnum.IDX_SAAS_OUTSTOCK);
                if (count > 0) {
                    throw new XbbException(OutstockErrorCodeEnum.API_ERROR_212040);
                }
            } else {
                Map<String,Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                param.put(StringConstant.CORPID,corpid);
                param.put(StringConstant.DEL,DelEnum.NORMAL.getDel());
                param.put("firstRefId", linkDataId);
                param.put("formDataId", 0);
                param.put("businessType", XbbRefTypeEnum.OTHER_OUTSTOCK.getCode());
                param.put("flowStatusIn", Arrays.asList(FlowStatusEnum.APPROVAL_PENDING.getType(), FlowStatusEnum.IN_APPROVAL.getType()));
                param.put("sourceBusinessType", handlerExplainInLinkItemDTO.getLinkBusinessType());
                param.put("moduleType", 1);
                List<PaasProcessRelatedDataEntity> paasProcessRelatedDataList = paasProcessRelatedDataModel.findEntitys(param);
                if (!paasProcessRelatedDataList.isEmpty()) {
                    throw new XbbException(OutstockErrorCodeEnum.API_ERROR_212040);
                }
            }

        }

        try {
            for (FieldAttrEntity fieldAttrEntity : handlerExplainInLinkItemDTO.getExplainList()) {
                if (Objects.equals(fieldAttrEntity.getIsRedundant(),1)){
                    continue;
                }
                if (Objects.equals(fieldAttrEntity.getAttr(), OutstockEnum.REF_ID.getAttr())) {
                    RedundantTemplateTypeEnum redundantTemplateTypeEnum = RedundantTemplateTypeEnum.getByCode(handlerExplainInLinkItemDTO.getLinkBusinessType());
                    switch (redundantTemplateTypeEnum){
                        case TRANSFER:
                            // 开启审批时关联新建走了addGet，导致可编辑
                            fieldAttrEntity.setEditable(0);
                            fieldAttrEntity.setDefaultAttr(saasUpdateHelp.getDefaultAttrPojo(linkDataId, serialNo, paasFormDataEntityExt.getFormId()));
                            break;
                        case CONTRACT:
                        case RETURNED_PURCHASE:
                        case INVENTORY:
                        case PRODUCTIONORDER:
                        case WORKORDER:
                            fieldAttrEntity.setDefaultAttr(saasUpdateHelp.getDefaultAttrPojo(linkDataId, serialNo, paasFormDataEntityExt.getFormId()));
                            break;
                        default:
                            throw new XbbException(TemplateErrorCodeEnum.API_ERROR_350006);
                    }
                }else if (Objects.equals(fieldAttrEntity.getAttr(), OutstockEnum.WAREHOUSE_ID.getAttr())) {
                    RedundantTemplateTypeEnum redundantTemplateTypeEnum = RedundantTemplateTypeEnum.getByCode(handlerExplainInLinkItemDTO.getLinkBusinessType());
                    switch (redundantTemplateTypeEnum){
                        case INVENTORY:
                            fieldAttrEntity.setDefaultAttr(saasUpdateHelp.getDefaultAttrPojo(FastJsonHelper.getJsonArrOrDefaultFromFormData(dataList, InventoryEnum.WAREHOUSE_ID.getAttr(), new JSONArray())));
                            fieldAttrEntity.setEditable(0);
                            break;
                        case TRANSFER:
                            fieldAttrEntity.setDefaultAttr(saasUpdateHelp.getDefaultAttrPojo(FastJsonHelper.getJsonArrOrDefaultFromFormData(dataList, TransferEnum.OUT_WAREHOUSE_ID.getAttr(), new JSONArray())));
                            fieldAttrEntity.setEditable(0);
                            break;
                        case PRODUCTIONORDER:
                            fieldAttrEntity.setDefaultAttr(saasUpdateHelp.getDefaultAttrPojo(FastJsonHelper.getJsonArrOrDefaultFromFormData(dataList, ProductionOrderEnum.OUT_WAREHOUSE_ID.getAttr(), new JSONArray())));
                            break;
                        default:
                            break;
                    }
                }else if (Objects.equals(fieldAttrEntity.getAttr(),OutstockEnum.TYPE.getAttr())){
                    String value = OutstockTypeEnum.getByBuisenssType(handlerExplainInLinkItemDTO.getLinkBusinessType());
                    for (ItemPoJo itemPoJo : fieldAttrEntity.getItems()){
                        if (Objects.equals(value, itemPoJo.getValue())){
                            itemPoJo.setChecked(true);
                        } else {
                            itemPoJo.setChecked(false);
                        }
                    }
                }else if (Objects.equals(fieldAttrEntity.getAttr(),OutstockEnum.PRODUCT.getAttr())){
                    Integer type = OutstockTypeEnum.getByBuisenssTypeInt(handlerExplainInLinkItemDTO.getLinkBusinessType());
                    List<BusinessProductEntity> businessProductEntityList = formDataValidateProductHelp.searchUnOutstockProduct(handlerExplainInLinkItemDTO.getCorpid(),handlerExplainInLinkItemDTO.getLinkDataId(),type, true);
                    List<OneKeyProduceProductPojo> productList = handlerExplainInLinkItemDTO.getProductList();
                    if (!productList.isEmpty()) {
                        Set<Long> oneKeyProduceProductSet = new HashSet<>();
                        productList.forEach(item -> oneKeyProduceProductSet.add(item.getId()));
                        businessProductEntityList.removeIf(businessProductEntity -> !oneKeyProduceProductSet.contains(businessProductEntity.getId()));
                    }
                    JSONArray productArray = formatOutstockLinkAdd(businessProductEntityList,fieldAttrEntity,type, handlerExplainInLinkItemDTO);
                    productHelp.enableSrialCheck(handlerExplainInLinkItemDTO.getCorpid(), productArray, handlerExplainInLinkItemDTO);
                    String defaultType = "";
                    if (Objects.nonNull(fieldAttrEntity.getDefaultAttr()) && Objects.nonNull(fieldAttrEntity.getDefaultAttr().getDefaultType())) {
                        defaultType = fieldAttrEntity.getDefaultAttr().getDefaultType();
                    }
                    fieldAttrEntity.setDefaultAttr(saasUpdateHelp.setDefaultValue(productArray));
                    if (Objects.nonNull(defaultType) && !defaultType.isEmpty()) {
                        fieldAttrEntity.getDefaultAttr().setDefaultType(defaultType);
                    }
                }else if (Objects.equals(handlerExplainInLinkItemDTO.getLinkBusinessType(),XbbRefTypeEnum.CONTRACT.getCode()) && Objects.nonNull(customerEntityExt)){
                    if (Objects.equals(fieldAttrEntity.getAttr(),ContractOutstockEnum.LINK_CUSTOMER.getAttr())){
                        fieldAttrEntity.setDefaultAttr(saasUpdateHelp.getDefaultAttrPojo(customerEntityExt.getId(), customerEntityExt.getData().getString(CustomerManagementEnum.NAME.getAttr())));
                    }else if (Objects.equals(fieldAttrEntity.getAttr(),ContractOutstockEnum.CUSTOMER_PHONE.getAttr())){
                        JSONArray jsonArray = customerEntityExt.getData().getJSONArray(CustomerManagementEnum.PHONE.getAttr());
                        if(Objects.equals(fieldAttr.getIsOpen(), BasicConstant.ZERO) || Objects.equals(fieldAttr.getVisible(), BasicConstant.ZERO)){
                            jsonArray = new JSONArray();
                        }
                        fieldAttrEntity.setDefaultAttr(saasUpdateHelp.getDefaultAttrPojo(jsonArray));
                    }else if (Objects.equals(fieldAttrEntity.getAttr(),ContractOutstockEnum.CUSTOMER_ADDRESS.getAttr())){
                        fieldAttrEntity.setDefaultAttr(saasUpdateHelp.getDefaultAttrPojo(customerEntityExt.getData().getJSONObject(CustomerManagementEnum.ADDRESS.getAttr())));
                    }
                }else if (Objects.equals(handlerExplainInLinkItemDTO.getLinkBusinessType(),XbbRefTypeEnum.RETURNED_PURCHASE.getCode())){
                    if (Objects.equals(fieldAttrEntity.getAttr(),ReturnedPurchaseOutstockEnum.LINK_SUPPLIER.getAttr())){
                        fieldAttrEntity.setDefaultAttr(saasUpdateHelp.getDefaultAttrPojo(FastJsonHelper.getJsonArrOrDefaultFromFormData(dataList, ReturnedPurchaseEnum.LINK_SUPPLIER.getAttr(), new JSONArray())));
                    }
                }else if (Objects.equals(handlerExplainInLinkItemDTO.getLinkBusinessType(),XbbRefTypeEnum.WORK_ORDER.getCode())){
                    if (Objects.equals(fieldAttrEntity.getAttr(),WorkOrderOutstockEnum.LINK_CUSTOMER.getAttr())){
                        fieldAttrEntity.setDefaultAttr(saasUpdateHelp.getDefaultAttrPojo(FastJsonHelper.getJsonArrOrDefaultFromFormData(dataList, WorkOrderEnum.LINK_CUSTOMER.getAttr(), new JSONArray())));
                    }else if (Objects.equals(fieldAttrEntity.getAttr(),WorkOrderOutstockEnum.LINK_CONTACT.getAttr())){
                        fieldAttrEntity.setDefaultAttr(saasUpdateHelp.getDefaultAttrPojo(FastJsonHelper.getJsonArrOrDefaultFromFormData(dataList, WorkOrderEnum.LINK_CONTACT.getAttr(), new JSONArray())));
                    }else if (Objects.equals(fieldAttrEntity.getAttr(),WorkOrderOutstockEnum.CUSTOMER_PHONE.getAttr())){
                        JSONArray jsonArray = dataList.getJSONArray(WorkOrderEnum.CONTACT_INFORMATION.getAttr());
                        if (Objects.isNull(fieldAttrEntity.getSubForm()) || Objects.isNull(fieldAttrEntity.getSubForm().getItems())){
                            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
                        }
                        List<FieldAttrEntity> subExplainList = JSONArray.parseArray(JSON.toJSONString(fieldAttrEntity.getSubForm().getItems()), FieldAttrEntity.class);
                        Map<String,FieldAttrEntity> map = ExplainUtil.getExplainMapByList(subExplainList,"text_1");
                        FieldAttrEntity entity = map.get("text_1");
                        if (Objects.nonNull(entity)){
                            List<ItemPoJo> poJoList = entity.getItems();
                            if (Objects.nonNull(jsonArray)){
                                for (int i = 0; i < jsonArray.size(); i++) {
                                    JSONObject jsonObject = jsonArray.getJSONObject(i);
                                    if (Objects.nonNull(jsonObject)){
                                        String value = jsonObject.getString("text_1");
                                        boolean exist = false;
                                        if (Objects.nonNull(poJoList)){
                                            for (int j = 0; j < poJoList.size(); j++) {
                                                ItemPoJo  itemPoJo = poJoList.get(j);
                                                if (Objects.equals(itemPoJo.getValue(),value)){
                                                    exist = true;
                                                }
                                            }
                                            if (!exist){
                                                jsonObject.put("text_1","");
                                            }
                                        }
                                    }
                                }
                            }
                        }
                        fieldAttrEntity.setDefaultAttr(saasUpdateHelp.getDefaultAttrPojo(jsonArray));
                    }else if (Objects.equals(fieldAttrEntity.getAttr(),WorkOrderOutstockEnum.CUSTOMER_ADDRESS.getAttr())){
                        fieldAttrEntity.setDefaultAttr(saasUpdateHelp.getDefaultAttrPojo(dataList.getJSONObject(WorkOrderEnum.ADDRESS.getAttr())));
                    }

                } else if (Objects.equals(handlerExplainInLinkItemDTO.getLinkBusinessType(),XbbRefTypeEnum.TRANSFER.getCode())){
                    if (Objects.equals(fieldAttrEntity.getAttr(),OutstockEnum.MEMO.getAttr())){
                        fieldAttrEntity.setDefaultAttr(saasUpdateHelp.getDefaultAttrPojo(FastJsonHelper.getStringOrDefaultFromFormData(dataList, TransferEnum.MEMO.getAttr(), "")));
                    }
                }
            }
        } catch (XbbException e){
            throw e;
        } catch (Exception e) {
            LOG.error("outstockService.formatLinkAddExplain 执行出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
    }

    private JSONArray formatOutstockLinkAdd(List<BusinessProductEntity> businessProductEntityList, FieldAttrEntity fieldAttrEntity, Integer type, HandlerExplainInLinkItemDTO handlerExplainInLinkItemDTO) throws XbbException {
        String corpid = handlerExplainInLinkItemDTO.getCorpid();
        UserVO loginUser = handlerExplainInLinkItemDTO.getLoginUser();
        Long formId = handlerExplainInLinkItemDTO.getFormId();
        Long sourceFormId = handlerExplainInLinkItemDTO.getSourceFormId();
        Long linkDataId = handlerExplainInLinkItemDTO.getLinkDataId();

        JSONArray productArray = new JSONArray();
        List<Long> dataIdList = new ArrayList<>();
        OutstockTypeEnum outstockTypeEnum = OutstockTypeEnum.getByCode(type);
//        boolean isSource = Arrays.asList(OutstockTypeEnum.RETURNED_PURCHASE_OUTSTOCK, OutstockTypeEnum.CONTRACT_OUTSTOCK,OutstockTypeEnum.WORK_ORDER_OUTSTOCK).contains(outstockTypeEnum);
        LinkProductRelyEntity linkProductRelyEntity = linkProductRelyModel.getByAttrAndFormIdAndLinkFormId(corpid, OutstockEnum.PRODUCT.getAttr(), formId, sourceFormId, DelEnum.NORMAL.getDel());
        UserAndDepartmentGetDTO userAndDepartmentGetDTO = new UserAndDepartmentGetDTO();
        BeanUtil.copyProperties(handlerExplainInLinkItemDTO, userAndDepartmentGetDTO);
        UserAndDepartmentGetVO userAndDepartmentGetVO = userHelp.getUserDepartmentMap(userAndDepartmentGetDTO);
        Map<String, UserEntity> userMap = userAndDepartmentGetVO.getUserMap();
        Map<String, DepartmentEntity> departmentMap = userAndDepartmentGetVO.getDepartmentMap();
        JSONArray warehouseObj = new JSONArray();
        for (BusinessProductEntity entity : businessProductEntityList){
            JSONObject jsonObject = new JSONObject();
            jsonObject.put(OutstockProductEnum.PRODUCT.getAttr(),entity.getProductId());
            jsonObject.put(MultiUnitConstant.RATE, entity.getRate());
            jsonObject.put(OutstockProductEnum.NUM.getAttr(),entity.getProductNum());
            jsonObject.put(OutstockProductEnum.COST.getAttr(), Objects.isNull(entity.getCost()) ? 0D : entity.getCost());
            jsonObject.put(InstockProductEnum.UNIT.getAttr(), formDataValidateProductHelp.formatUnit(corpid,entity.getProductUnit()));
            jsonObject.put(OutstockProductEnum.MEMO.getAttr(),entity.getMemo());
            jsonObject.put(OutstockProductEnum.WAREHOUSE.getAttr(),entity.getWarehouseId());
            if (Objects.equals(type, OutstockTypeEnum.RETURNED_PURCHASE_OUTSTOCK.getCode())) {
                JSONObject data = entity.getData();
                if (Objects.nonNull(data)) {
                    jsonObject.put(SelectProductEnum.WAREHOUSE.getAttr(), data.get(SelectProductEnum.WAREHOUSE.getAttr()));
                    jsonObject.put(SelectProductEnum.BATCH.getAttr(), data.getString(SelectProductEnum.BATCH.getAttr()));
                    if (Objects.nonNull(data.getLong(SelectProductEnum.PRODUCE_DATE.getAttr())) && data.getLong(SelectProductEnum.PRODUCE_DATE.getAttr()) > 0L) {
                        jsonObject.put(SelectProductEnum.GUARANTEE_PERIOD.getAttr(), data.getLong(SelectProductEnum.GUARANTEE_PERIOD.getAttr()));
                    }
                    jsonObject.put(SelectProductEnum.PRODUCE_DATE.getAttr(), data.getLong(SelectProductEnum.PRODUCE_DATE.getAttr()));
                }
            }else {
                jsonObject.put(OutstockProductEnum.BATCH.getAttr(), entity.getBatch());
                jsonObject.put(OutstockProductEnum.PRODUCE_DATE.getAttr(),entity.getProduceDate());
                if (Objects.nonNull(entity.getProduceDate()) && entity.getProduceDate() > 0L) {
                    jsonObject.put(OutstockProductEnum.GUARANTEE_PERIOD.getAttr(),entity.getGuaranteePeriod());
                }
            }
            if (Objects.equals(OutstockTypeEnum.CONTRACT_OUTSTOCK.getCode(),type)){
                jsonObject.put(ContractOutstockProductEnum.SELLING_PRICE.getAttr(), entity.getPrice());
                jsonObject.put(ContractOutstockProductEnum.DISCOUNT.getAttr(), entity.getDiscount());
                jsonObject.put(ContractOutstockProductEnum.SUBTOTAL.getAttr(), entity.getProductNum() * entity.getPrice());
                jsonObject.put(ContractOutstockProductEnum.PRICE.getAttr(), entity.getHistoricalPrice());
            }
            if (Objects.nonNull(entity.getRefProductId())) {
                jsonObject.put(BusinessConstant.REF_PRODUCT_ID, entity.getRefProductId());
            }
            jsonObject.put(BusinessConstant.PRODUCT_SUB_ID,0);
            productArray.add(jsonObject);
            dataIdList.add(entity.getProductId());
        }
        JSONObject productData = new JSONObject();
        productData.put(OutstockEnum.PRODUCT.getAttr(),productArray);
        //sku成本
        Map<Object,Double> costMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Map<Object,Double> stockMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        //sku单价
        Map<Long,Double> priceMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);

        boolean updatePrice = Objects.equals(type,OutstockTypeEnum.CONTRACT_OUTSTOCK.getCode());

        //调拨、盘点、领料产品要拿仓库产品成本
        //合同、采购退货、工单、库存
        if (Objects.equals(outstockTypeEnum.getCode(),OutstockTypeEnum.TRANSFER_OUTSTOCK.getCode()) || Objects.equals(outstockTypeEnum.getCode(),OutstockTypeEnum.INVENTORY_OUTSTOCK.getCode())){
            // 调拨出库的关联产品取调拨单出库仓库的产品
            warehouseObj = formDataValidateProductHelp.getWarehouseObj(corpid,linkDataId,outstockTypeEnum.getBusinessType(),false);
            Long warehouseId = warehouseObj.getJSONObject(0).getLong("id");
            formDataValidateProductHelp.getSkuWarehouseOrBatchCost(productArray, warehouseId, corpid, costMap,stockMap);
        }else if(Objects.equals(outstockTypeEnum.getCode(),OutstockTypeEnum.RETURNED_PURCHASE_OUTSTOCK.getCode()) || Objects.equals(outstockTypeEnum.getCode(),OutstockTypeEnum.MATERIEL_OUTSTOCK.getCode())){
            formDataValidateProductHelp.getSkuWarehouseOrBatchCost(productArray, corpid, costMap, stockMap);
        }else {
            costMap = formDataValidateProductHelp.getAllSkuCost(dataIdList,corpid);
        }
        if (updatePrice){
            priceMap = formDataValidateProductHelp.getSkuPrice(dataIdList,corpid);
        }
        //分仓库存和成本
        Map<Long,Map<String,JSONObject>> productMap = formDataValidateProductHelp.getWarehouseMap(dataIdList,corpid);
        JSONArray newProductArray = formDataValidateProductHelp.otherProductToAnother(productData,fieldAttrEntity,OutstockEnum.PRODUCT.getAttr(),OutstockEnum.PRODUCT.getAttr(),corpid, loginUser, handlerExplainInLinkItemDTO.getBusinessType(), handlerExplainInLinkItemDTO.getLinkBusinessType());
        // 关联产品自定义字段联动
        DefaultAttrPoJo defaultAttr = fieldAttrEntity.getDefaultAttr();
        String defaultType = defaultAttr.getDefaultType();
        // 源单解释
        Map<String, FieldAttrEntity> sourceExplainMap = null;
        // 当前表单解释
        Map<String, FieldAttrEntity> thisExplainMap = null;
        // 当前表单某个关联产品解释
        Map<String, FieldAttrEntity> subThisExplainMap = null;
        // 源单某个关联产品解释
        Map<String, FieldAttrEntity> subSourceExplainMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        // 当前表单某个关联产品子字段与源单某个关联产品对应关系
        Map<String, String> thisToTarget = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        if (Objects.nonNull(defaultType) && Objects.equals(defaultType, DefaultTypeEnum.PRODUCT_DATA_RELY.getAlias()) && Objects.nonNull(linkProductRelyEntity)) {
            // 源数据表单
            PaasFormExplainEntity paasFormExplainEntity = proFormHelp.getExplainEntity(corpid, linkProductRelyEntity.getSourceFormId(), linkProductRelyEntity.getSourceBusinessType());
            List<FieldAttrEntity> explainList = JSONArray.parseArray(paasFormExplainEntity.getExplains(), FieldAttrEntity.class);
            sourceExplainMap = ExplainUtil.getExplainMapByList(explainList, null);
            // 当前表单解释
            PaasFormExplainEntity displayFormExplain = proFormHelp.getExplainEntity(corpid, linkProductRelyEntity.getFormId(), linkProductRelyEntity.getBusinessType());
            thisExplainMap = ExplainUtil.getExplainMap(displayFormExplain.getExplains(), null);
            subThisExplainMap = businessProductService.getProductRelyMap(OutstockEnum.PRODUCT.getAttr(), linkProductRelyEntity, sourceExplainMap, thisExplainMap, subSourceExplainMap, thisToTarget);
            for (BusinessProductEntity entity : businessProductEntityList){
                JSONObject entityData = entity.getData();
                if (Objects.nonNull(entityData) && !thisToTarget.isEmpty()) {
                    ParseSingleRowDataDTO parseSingleRowDataDTO = new ParseSingleRowDataDTO();
                    parseSingleRowDataDTO.setDataJsonObject(entityData);
                    parseSingleRowDataDTO.setUserMap(userMap);
                    parseSingleRowDataDTO.setDepartmentMap(departmentMap);
                    parseSingleRowDataDTO.setExplainMap(subSourceExplainMap);
                    ParseSingleRowDataVO parseSingleRowDataVO = formDataUpdateGetAnalysisDataHelp.parseSingleRowData(parseSingleRowDataDTO);
                    if (Objects.isNull(parseSingleRowDataVO)) {
                        throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.PARSE_SINGLE_ROW_DATA_FAILED);
                    }
                    JSONObject result = parseSingleRowDataVO.getResult();
                    JSONObject thisData = businessProductService.formatThisFormData(subThisExplainMap, thisToTarget, result);
                    for (int i = 0; i < newProductArray.size(); i++) {
                        JSONObject jsonObject = newProductArray.getJSONObject(i);
                        if (Objects.equals(jsonObject.getLongValue(BusinessConstant.REF_PRODUCT_ID), entity.getRefProductId())) {
                            jsonObject.putAll(thisData);
                            break;
                        }
                    }
                }
            }
        }
        for (int i = 0;i < newProductArray.size();i++){
            JSONObject jsonObject = newProductArray.getJSONObject(i);
            JSONObject product = jsonObject.getJSONObject(SelectProductEnum.PRODUCT.getAttr());
            Long productId = product.getLong("dataId");
            JSONObject sourceData = new JSONObject();
            Map<String, JSONObject> warehouseMap = productMap.getOrDefault(productId, new HashMap<>());
            sourceData.put("warehouse", warehouseMap);
            product.put("sourceData",sourceData);
            String batch = jsonObject.getString(SelectProductEnum.BATCH.getAttr());
            Long warehouseId = 0L;
            double rate = Objects.nonNull(jsonObject.getDouble(MultiUnitConstant.RATE)) ? jsonObject.getDouble(MultiUnitConstant.RATE) : 1D;
            if (Objects.equals(outstockTypeEnum.getCode(), OutstockTypeEnum.RETURNED_PURCHASE_OUTSTOCK.getCode()) || Objects.equals(outstockTypeEnum.getCode(), OutstockTypeEnum.MATERIEL_OUTSTOCK.getCode())) {
                //采购退货入库和生产领料每个产品的仓库可能不一样
                if (Objects.nonNull(jsonObject.getLong(SelectProductEnum.WAREHOUSE.getAttr()))) {
                    warehouseId = jsonObject.getLong(SelectProductEnum.WAREHOUSE.getAttr());
                    JSONArray singleWarehouseObj = new JSONArray();
                    JSONObject returnWarehouseObj = new JSONObject();
                    returnWarehouseObj.put("id", jsonObject.getLong(SelectProductEnum.WAREHOUSE.getAttr()));
                    returnWarehouseObj.put("name", warehouseMap.getOrDefault(jsonObject.getString(SelectProductEnum.WAREHOUSE.getAttr()), new JSONObject()).getString(ProductEnum.WAREHOUSE.getSaasAttr()));
                    singleWarehouseObj.add(returnWarehouseObj);
                    jsonObject.put(OutstockProductEnum.WAREHOUSE.getAttr(), singleWarehouseObj);
                }
            }else {
                jsonObject.put(OutstockProductEnum.WAREHOUSE.getAttr(), warehouseObj);
                if (!warehouseObj.isEmpty()) {
                    warehouseId = warehouseObj.getJSONObject(0).getLong("id");
                }
            }
            //分为取批次成本丶库存和分仓成本丶库存
            Object key;
            if (StringUtil.isNotEmpty(batch)) {
                key = formDataValidateProductHelp.getBatchKey(productId, warehouseId, batch, jsonObject.getLong(SelectProductEnum.PRODUCE_DATE.getAttr()), FastJsonHelper.getLongOrDefaultFromFormData(jsonObject, SelectProductEnum.GUARANTEE_PERIOD.getAttr(), 0L) * TimeConstant.SECONDS_PER_DAY);
            }else {
                key = productId + "_" + warehouseId;
            }

            if (Objects.equals(outstockTypeEnum.getCode(),OutstockTypeEnum.TRANSFER_OUTSTOCK.getCode()) || Objects.equals(outstockTypeEnum.getCode(),OutstockTypeEnum.INVENTORY_OUTSTOCK.getCode()) || Objects.equals(outstockTypeEnum.getCode(),OutstockTypeEnum.MATERIEL_OUTSTOCK.getCode()) || Objects.equals(outstockTypeEnum.getCode(),OutstockTypeEnum.RETURNED_PURCHASE_OUTSTOCK.getCode())){
                //分为取批次库存和分仓库存
                if (Objects.nonNull(stockMap.get(key))) {
                    jsonObject.put(OutstockProductEnum.STOCK.getAttr(), stockMap.get(key));
                }
            }
            if (Objects.equals(outstockTypeEnum.getCode(),OutstockTypeEnum.RETURNED_PURCHASE_OUTSTOCK.getCode())){
//                jsonObject.put(OutstockProductEnum.COST.getAttr(), jsonObject);
                JSONObject data = product.getJSONObject("data");
                data.put(SelectProductEnum.SOURCE_PRICE.getAttr(),jsonObject.get(SelectProductEnum.COST.getAttr()));
            }else {
                //分为取批次成本和分仓成本
                if (Objects.nonNull(jsonObject.get(ProductConstant.SELLING_PRICE_MAP))) {
                    JSONObject sellingMap = jsonObject.getJSONObject(ProductConstant.SELLING_PRICE_MAP);
                    if (!Objects.equals(outstockTypeEnum.getCode(),OutstockTypeEnum.MATERIEL_OUTSTOCK.getCode())){
                        sellingMap.put(OutstockProductEnum.COST.getAttr(), Arith.mul(rate, costMap.getOrDefault(key, 0D)));
                    }else {
                        sellingMap.put(OutstockProductEnum.COST.getAttr(), costMap.getOrDefault(key, 0D));
                    }
                }
                jsonObject.put(OutstockProductEnum.COST.getAttr(), Arith.mul(rate, costMap.getOrDefault(key, 0D)));
            }
            if (Objects.equals(outstockTypeEnum.getCode(),OutstockTypeEnum.CONTRACT_OUTSTOCK.getCode())){
                JSONObject data = product.getJSONObject("data");
                data.put(SelectProductEnum.SOURCE_PRICE.getAttr(),jsonObject.get(SelectProductEnum.SELLING_PRICE.getAttr()));
            }
            if (updatePrice && Objects.isNull(jsonObject.get(ContractOutstockProductEnum.PRICE.getAttr()))){
                jsonObject.put(ContractOutstockProductEnum.PRICE.getAttr(), priceMap.getOrDefault(productId, 0D));
            }
            JSONObject batchJson = new JSONObject();
            if (!StringUtil.isEmpty(batch)) {
                batchJson.put("value", batch);
                batchJson.put("text", batch);
                jsonObject.put(OutstockProductEnum.BATCH.getAttr(),batchJson);
            }
            jsonObject.put(OutstockProductEnum.TOTAL_COST.getAttr(),jsonObject.getDouble(OutstockProductEnum.COST.getAttr()) * jsonObject.getDouble(OutstockProductEnum.NUM.getAttr()));
            if (Objects.nonNull(jsonObject.get(SelectProductEnum.PRODUCE_DATE.getAttr())) && Objects.nonNull(jsonObject.getLong(SelectProductEnum.GUARANTEE_PERIOD.getAttr()))) {
                jsonObject.put(OutstockProductEnum.EXPIRE_DATE.getAttr(), jsonObject.getLong(SelectProductEnum.PRODUCE_DATE.getAttr()) + jsonObject.getLong(SelectProductEnum.GUARANTEE_PERIOD.getAttr()) * TimeConstant.SECONDS_PER_DAY);
            }
        }
        return newProductArray;
    }

    private void updateBatch(OutstockUpdateBatchDTO outstockUpdateBatchDTO) throws XbbException {
        try {
            List<UpdateDataEntity> updateDataList = new ArrayList<>();
            String corpid = outstockUpdateBatchDTO.getCorpid();
            outstockUpdateBatchDTO.getOutstockList().forEach((item)->{
                UpdateDataEntity updateDataEntity = ExplainUtil.getUpdateData(item.getId(), item.getData(), corpid);
                updateDataList.add(updateDataEntity);
            });
            if (!updateDataList.isEmpty()) {
                outstockModel.updateBatch(updateDataList, corpid);
            }
        } catch (Exception e) {
            LOG.error("outstockService.updateBatch 执行出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
    }

    @Override
    public void formatUpdateExplain(FormatExplainDTO formatExplainDTO) throws XbbException {
        formatExplainDTO.setEditFormat(true);
        String corpid = formatExplainDTO.getCorpid();
        formatAddExplain(formatExplainDTO);
        Integer type = formatExplainDTO.getResult().getInteger(OutstockEnum.TYPE.getAttr());
        // 编辑时产品仓库不可以修改，审批编辑除外（同新建）
        List<FieldAttrEntity> explainList = formatExplainDTO.getExplainList();
        JSONObject data = formatExplainDTO.getResult();
        data.put(OutstockEnum.TYPE.getAttr(),data.getString(OutstockEnum.TYPE.getAttr()));
        Integer outstockType = data.getInteger(OutstockEnum.TYPE.getAttr());
        Integer linkBusinessType = null;
        if (Objects.equals(outstockType, OutstockTypeEnum.RETURNED_PURCHASE_OUTSTOCK.getCode())) {
            linkBusinessType = OutstockTypeEnum.RETURNED_PURCHASE_OUTSTOCK.getBusinessType();
        } else if (Objects.equals(outstockType, OutstockTypeEnum.CONTRACT_OUTSTOCK.getCode())) {
            linkBusinessType = OutstockTypeEnum.CONTRACT_OUTSTOCK.getBusinessType();
        } else if (Objects.equals(outstockType, OutstockTypeEnum.INVENTORY_OUTSTOCK.getCode())) {
            linkBusinessType = OutstockTypeEnum.INVENTORY_OUTSTOCK.getBusinessType();
        } else if (Objects.equals(outstockType, OutstockTypeEnum.TRANSFER_OUTSTOCK.getCode())) {
            linkBusinessType = OutstockTypeEnum.TRANSFER_OUTSTOCK.getBusinessType();
        } else if (Objects.equals(outstockType, OutstockTypeEnum.ASSEMBLE_OUTSTOCK.getCode())) {
            linkBusinessType = OutstockTypeEnum.ASSEMBLE_OUTSTOCK.getBusinessType();
        } else if (Objects.equals(outstockType, OutstockTypeEnum.WORK_ORDER_OUTSTOCK.getCode())) {
            linkBusinessType = OutstockTypeEnum.WORK_ORDER_OUTSTOCK.getBusinessType();
        } else if (Objects.equals(outstockType, OutstockTypeEnum.MATERIEL_OUTSTOCK.getCode())) {
            linkBusinessType = OutstockTypeEnum.MATERIEL_OUTSTOCK.getBusinessType();
        }
        for (FieldAttrEntity fieldAttrEntity : explainList) {
            Integer fieldType = fieldAttrEntity.getFieldType();
            String attr = fieldAttrEntity.getAttr();
            if (Objects.equals(fieldType, FieldTypeEnum.SELECT_PRODUCT.getType())) {
                fieldAttrEntity.setSupportScanning(BasicConstant.ONE);
                if (Objects.isNull(formatExplainDTO.getFromCopy()) || !formatExplainDTO.getFromCopy()) {
                    fieldAttrEntity.setEditable(0);
                    List<? extends FieldAttrEntity> subExplainList = fieldAttrEntity.getSubForm().getItems();
                    subExplainList.forEach(item -> item.setEditable(0));
                    fieldAttrEntity.getSubForm().setItems(subExplainList);
                }
            } else if (Objects.equals(fieldType, FieldTypeEnum.LINK_BUSINESS_MULTI.getType()) || Objects.equals(fieldType, FieldTypeEnum.LINK_BUSINESS_SINGLE.getType())) {
                fieldAttrEntity.setEditable(0);
            }
            if (Objects.equals(attr, OutstockEnum.WAREHOUSE_ID.getAttr())) {
                fieldAttrEntity.setEditable(0);
            }else if (Objects.equals(attr, OutstockEnum.TYPE.getAttr())) {
                fieldAttrEntity.setEditable(0);
            }else if (Objects.equals(attr, OutstockEnum.REF_ID.getAttr())) {
                fieldAttrEntity.setLinkedType(linkBusinessType);
            }else if (Objects.equals(attr, ContractOutstockEnum.LINK_CUSTOMER.getAttr()) && Objects.equals(type,OutstockTypeEnum.CONTRACT_OUTSTOCK.getCode())){
                fieldAttrEntity.setEditable(0);
            }else if (Objects.equals(attr, OutstockEnum.TIME.getAttr())) {
                fieldAttrEntity.setEditable(0);
            }
        }
    }

    @Override
    public void formatBatchExplain(List<FieldAttrEntity> fieldAttrEntityList, String enable) {
        String productAttr = OutstockEnum.PRODUCT.getAttr();
        BatchSeqExplainHelp.getInstance().formatExplain4BatchAffectProductAttr(fieldAttrEntityList, enable, productAttr);
    }

}
